1 说明
实现功能:
扫描指定文件目录下文件,通过scp上传到指定服务器目录下
程序结构简单说明:
- 包含两个线程,线程一:扫描文件线程;线程二:消费文件线程;
- 线程一:扫描指定文件目录下文件,把符合要求的文件名加入到全局列表中;
- 线程二:遍历全局列表,取出文件名,并获取该文件最后修改时间;
- 判断文件最后修改时间与当前时间只差是否大于阈值;
- 如果大于阈值则通过scp上传文件到指定服务器,上传成功删除文件并从全局列表中移除。
2 SSH免密登录环境
因为是通过scp自动上传,无需人工干预,所以需要配置两台服务的ssh免密登录;
假如本次服务器分别为A和B,A上传文件到B,按照如下步骤配置ssh免密登录环境:
1)在A机下生成公钥/私钥对。
[root@A ~]# ssh-keygen -t rsa -P ''
-P表示密码,-P '' 就表示空密码,也可以不用-P参数,这样就要三车回车,用-P就一次回车。
该命令将在/root/.ssh目录下面产生一对密钥id_rsa和id_rsa.pub。
一般采用的ssh的rsa密钥:
id_rsa 私钥
id_rsa.pub 公钥
下述命令产生不同类型的密钥
ssh-keygen -t dsa
ssh-keygen -t rsa
ssh-keygen -t rsa1
2)把A机下的/root/.ssh/id_rsa.pub 复制到B机的 /root/.ssh/authorized_keys文件里,先要在B机上创建好 /root/.ssh 这个目录,用scp复制。
[root@A ~]# scp /root/.ssh/id_rsa.pub root@192.168.1.181:/root/.ssh/authorized_keys
root@192.168.1.181's password:
id_rsa.pub 100% 223 0.2KB/s 00:00
由于还没有免密码登录的,所以要输入一次B机的root密码。
3)authorized_keys的权限要是600
[root@B ~]# chmod 600 /root/.ssh/authorized_keys
4)A机登录B机
[root@A ~]# ssh -l root 192.168.1.181
The authenticity of host '192.168.1.181 (192.168.1.181)' can't be established.
RSA key fingerprint is 00:a6:a8:87:eb:c7:40:10:39:cc:a0:eb:50:d9:6a:5b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.181' (RSA) to the list of known hosts.
Last login: Thu Jul 3 09:53:18 2008 from root
[root@B ~]#
第一次登录是时要你输入yes。
现在A机可以无密码登录B机了。
想让A,B机无密码互登录,那B机以上面同样的方式配置即可。
3 python源码
#coding=utf-8
"""
作用说明:
通过scp上传文件,需要两台无服务预先配置好ssh无密登录,至于如何配置
可以网上查看教程。
线程一:扫描指定文件目录下的文件,并添加到全局列表中
线程二:扫描全局列表,把文件上传到指定的服务器中,
上传成功则删除该文件,并从全局列表中移除
"""
from threading import Thread, Lock
import signal
import time
import datetime
import os
import sys
ftp_list = [] # 全局列表
flag_time = 5 # 时间阈值,表示当前时间戳与文件最后修改时间大于该值时才操作
ftp_path="/tmp/data" # 示例:要扫描的文件目录
server=" root@192.168.101.22:/data/" # 示例:上传到服务器的文件目录
"""
path:要扫描的文件目录
file_list: 将扫描到文件加入该列表中
key: 扫描文件时,有的文件不需要,以key关键词
判断该文件是否为需要的文件
"""
def get_file_list(path, file_list, key):
files=os.listdir(path)
for f in files:
if key not in f:
continue
file_with_path = path+"/"+f
if file_with_path in file_list:
continue
if not os.path.isdir(file_with_path):
try:
time_str = os.path.getmtime(file_with_path)
file_time = int(time_str)
now_time = int(time.time())
#print("time :", now_time-file_time)
except OSError as err:
continue
if((now_time-file_time) > flag_time):
lock.acquire()
file_list.append(file_with_path)
lock.release()
#print("[## add ##]add file %s to global list"% file_with_path)
"""
file_list: 扫描文件列表,并把文件上传到服务器,
上传成功后,删除文件,并从全局列表中移除
"""
def send_file(file_list):
year = datetime.datetime.now().year
month = datetime.datetime.now().month
day = datetime.datetime.now().day
for f in file_list:
if f.strip():
#上传到服务指定目录下子目录以 年月日 分类
shell_cmd="scp "+f+server+"/"+str(year)+"/"+str(month)+"/"+str(day)
ret_shell=os.system(shell_cmd)
#print("shellcmd:",shell_cmd)
lock.acquire()
file_list.remove(f)
lock.release()
os.remove(f)
#print("[-- remove --]remove file %s "% f)
def quit(signum, frame):
print("You choose to stop me")
sys.exit()
"""
线程一:扫描文件目录,将符合要求文件名添加到全局列表中
"""
def traverse_dir():
global ftp_list
while True:
get_file_list(ftp_path, ftp_list, ".bin")
time.sleep(2)
#print("======================== start to traverse ===========================");
#print("[traverse]:%s"% ftp_list)
"""
线程二:扫描全局列表,将文件上传到指定服务器,
上传成功,删除文件,并从全局列表中移除
"""
def consume_file():
global ftp_list
while True:
send_file(ftp_list)
time.sleep(2)
#print("consume:%s"%ftp_list)
if __name__=='__main__':
try:
signal.signal(signal.SIGINT, quit)
signal.signal(signal.SIGTERM, quit)
lock = Lock() #创建线程锁
thread_product = Thread(target=traverse_dir)
thread_consume = Thread(target=consume_file)
thread_product.setDaemon(True)
thread_product.start()
thread_consume.setDaemon(True)
thread_consume.start()
while True:
pass
except Exception, exc:
print exc