说明:需求是为了实现文件分发效果,进行数据保存操作,要求使用python实现。
背景:
1.如上图所示,现在环境内有一台服务器,服务器内有一个读写性能不在考虑范围内的固态硬盘,若干个机械盘,每个机械盘的读写速度在100m/s
2.由于服务器内每分钟能生成大量的日志文件,而且每个日志文件内容大概在1G,所以直接存入机械盘速度有点吃不消,但是存在固态盘内成本就有点吃不消,所以使用1T的固态盘进行中转操作,就是生成的日志会存在固态盘内,然后进行分发到机械盘内。
需求:
1.日志文件的文件名为“qwerasdf.log”,但是正在生成的日志文件还未生成成功的日志文件名为“qwerasdf.log.tmp”。日志的文件为加密文件,文件名称毫无规律。
2.要求实时检测文件夹内的文件情况进行分发,为了提高移动效率,必须同时对多个盘进行进行移动操作,不能出现一个日志文件出现在多的硬盘的情况,未生成完毕的文件(qwerasdf.log.tmp)文件不能进行移动操作。
3.移动时,每个机械硬盘同一时间只能存在一个文件正在进行移动。
4.需要检测目标硬盘的剩余空间容量,空间不足10G将停止移动。
提示:
1.日志服务器会对日志文件目录进行扫描然后自动整合所以不需要考虑文件移动顺序问题,你就给我无脑移动就行。
2.没有二级目录,直接存在固态和机械的根目录下。只需要考虑移动文件就行,不需要移动文件夹。
文件分发的代码我自己没有去写,我看网上有挺多的资料的啊,你可以去找找看,有些也挺符合你的要求的,比如:
python实现文件分发效果进行数据保存:https://blog.csdn.net/feng1790291543/article/details/131138816
python实现多个文件的分发:https://www.cnblogs.com/uglyliu/p/6269024.html
在这些基础上在做些修改,以符合你的需求。你要完全和你的要求一字不差有点困难。只能说在已有的基础上在去扩展。
参考示例
import os
import time
import shutil
# 固态盘路径
ssd_path = "/path/to/ssd"
# 机械盘路径
hdd_paths = ["/path/to/hdd1", "/path/to/hdd2", "/path/to/hdd3"]
# 检查固态盘内是否有未生成完毕的日志文件
def has_unfinished_logs():
unfinished_logs = [f for f in os.listdir(ssd_path) if f.endswith(".log.tmp")]
return len(unfinished_logs) > 0
# 在指定机械盘中检查可用空间是否足够
def has_enough_space_in_hdd(hdd_path):
available_space = shutil.disk_usage(hdd_path).free
return available_space > 10 * 1024 * 1024 * 1024 # 10GB
# 获取下一个可用的机械盘路径
def get_next_available_hdd_path():
for hdd_path in hdd_paths:
if has_enough_space_in_hdd(hdd_path):
return hdd_path
return None
# 检查当前机械盘上是否有正在移动的文件
def is_hdd_in_use(hdd_path):
hdd_files = [f for f in os.listdir(hdd_path) if f.endswith(".log")]
return len(hdd_files) > 0
# 移动文件
def move_files():
# 检查是否有未完成的日志文件,如果有则跳过
if has_unfinished_logs():
return
# 获取下一个可用的机械盘路径
next_hdd_path = get_next_available_hdd_path()
if not next_hdd_path:
print("No available HDD")
return
# 检查机械盘是否正在被占用
if is_hdd_in_use(next_hdd_path):
print("HDD is in use")
return
# 获取固态盘中的日志文件列表
ssd_logs = [f for f in os.listdir(ssd_path) if f.endswith(".log")]
# 执行移动操作
for log_file in ssd_logs:
src_path = os.path.join(ssd_path, log_file)
dst_path = os.path.join(next_hdd_path, log_file)
# 检查机械盘剩余空间是否足够
if not has_enough_space_in_hdd(next_hdd_path):
print("HDD out of space")
break
# 移动文件
shutil.move(src_path, dst_path)
# 循环执行移动操作
while True:
move_files()
time.sleep(1) # 每隔1秒检查一次
以下是一个可能的Python实现,实现了上述需求:
import os
import shutil
import time
# 固态盘路径
ssd_path = "/mnt/ssd/"
# 机械盘路径列表
hdd_paths = ["/mnt/hdd0/", "/mnt/hdd1/", "/mnt/hdd2/"]
# 目标文件名
target_filename = "qwerasdf.log"
# 未完成的文件名
temp_filename = "qwerasdf.log.tmp"
# 每个机械盘同一时间只能存在一个文件正在移动
hdd_locks = [False] * len(hdd_paths)
# 最小剩余空间
min_free_space = 10 * 1024 * 1024 * 1024 # 10G
def move_file(src_path, dst_path):
# 获取目标硬盘剩余空间大小
free_space = shutil.disk_usage(dst_path).free
# 如果目标硬盘剩余空间不足10G,停止移动
if free_space < min_free_space:
print("Destination disk is full. Stop moving file.")
return
# 获取目标路径
dst_file = os.path.join(dst_path, target_filename)
# 如果目标路径已经存在,则不进行移动操作
if os.path.exists(dst_file):
return
# 获取源路径
src_file = os.path.join(src_path, target_filename)
# 如果源文件不存在,则不进行移动操作
if not os.path.exists(src_file):
return
# 获取未完成的文件路径
temp_file = os.path.join(src_path, temp_filename)
# 如果未完成的文件存在,则不进行移动操作
if os.path.exists(temp_file):
return
# 获取目标机械硬盘的索引
index = hdd_paths.index(dst_path)
# 如果该机械硬盘已经有文件正在移动,则不进行移动操作
if hdd_locks[index]:
return
# 上锁
hdd_locks[index] = True
# 进行移动操作
try:
shutil.move(src_file, dst_file)
print("File moved from", src_file, "to", dst_file)
except Exception as e:
print("Failed to move file:", e)
# 解锁
hdd_locks[index] = False
while True:
# 遍历固态盘的文件夹
for filename in os.listdir(ssd_path):
path = os.path.join(ssd_path, filename)
# 如果是文件夹则跳过
if os.path.isdir(path):
continue
# 如果不是目标文件则跳过
if filename != target_filename:
continue
# 如果是未完成的文件则跳过
if temp_filename in filename:
continue
# 遍历机械盘,进行移动操作
for hdd_path in hdd_paths:
move_file(ssd_path, hdd_path)
# 定时检测
time.sleep(1)
这个程序会不断地遍历固态盘根目录下的文件,如果发现目标文件,则会尝试将该文件移动到机械盘中。在移动过程中,程序会进行各种检查,如检查目标机械硬盘是否有足够的剩余空间,是否已经有文件正在移动等等。程序会每秒钟检测一次,以实现实时的文件分发效果。