linux利用python编写计划任务同步文件

python利用rsync每隔30秒同步一次文件并记录到日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import subprocess
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler

def sync_files():
# 原始路径
source_path = "/home/dev/192.168.10.114"
# 目标路径,如果是远程目录,需要配置ssh免密,否则需要输入密码
destination_path = "/tmp/"

# 获取当前时间作为日志记录时间
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_message = f"[{timestamp}] Starting file synchronization...\n"

try:
rsync_cmd = f"rsync -avz --delete {source_path} {destination_path}"
output = subprocess.check_output(rsync_cmd, shell=True, stderr=subprocess.STDOUT)
log_message += output.decode("utf-8") + "\n"

log_message += f"[{timestamp}] File synchronization completed successfully.\n"
except subprocess.CalledProcessError as e:
log_message += f"[{timestamp}] File synchronization failed. Error: {e.output.decode('utf-8')}\n"

# 将日志写入文件
with open("/tmp/log.txt", "a") as log_file:
log_file.write(log_message)

if __name__ == '__main__':
scheduler = BlockingScheduler()
scheduler.add_job(sync_files, 'interval', seconds=30)
scheduler.start()

代码中subprocess.check_output和supprocess.call的不同

subprocess.callsubprocess.check_output是Python的subprocess模块提供的两个函数,用于执行外部命令。它们之间的区别如下:

  1. subprocess.call

    • 功能:call函数用于执行指定的命令,并等待命令执行完成后返回。
    • 返回值:返回命令的执行状态,一般情况下,返回值为0表示命令执行成功,非零值表示命令执行失败。
    • 输出:命令的输出将直接打印到标准输出。
  2. subprocess.check_output

    • 功能:check_output函数用于执行指定的命令,并等待命令执行完成后返回命令的输出结果。
    • 返回值:返回命令的输出结果(字节串类型)。
    • 异常:如果命令执行失败(返回值非零),则会引发CalledProcessError异常。

因此,call函数适用于只需要执行命令并检查执行状态的情况,而check_output函数适用于需要获取命令执行的输出结果的情况。

需要注意的是,callcheck_output函数都是同步执行的,即程序会在执行命令的过程中暂停等待,直到命令执行完成。如果需要异步执行命令,可以考虑使用subprocess.Popen函数。

下面是一个简单的示例,演示了callcheck_output函数的使用:

1
2
3
4
5
6
7
8
9
10
import subprocess

# 使用call函数执行命令
exit_code = subprocess.call("ls -l", shell=True)
print("Command executed with exit code:", exit_code)

# 使用check_output函数执行命令并获取输出结果
output = subprocess.check_output("ls -l", shell=True)
print("Command output:")
print(output.decode("utf-8"))

在上述示例中,首先使用call函数执行了一个ls -l的命令,并将执行状态存储在exit_code变量中,然后打印了执行状态。接下来,使用check_output函数执行同样的命令,并将输出结果存储在output变量中,最后打印了输出结果。

请注意,shell=True参数用于在shell环境中执行命令,decode("utf-8")用于将输出结果从字节串转换为字符串。

添加到开机自启动

要将该同步脚本作为Linux系统的守护进程,并实现开机自启动,你可以使用Systemd服务来完成。Systemd是现代Linux系统的守护进程管理器,它提供了管理和控制系统服务的功能。

以下是具体的设置步骤:

  1. 创建一个Systemd服务配置文件。

在Linux系统中,Systemd服务配置文件通常存储在/etc/systemd/system/目录下,以.service为后缀。你可以选择在该目录下创建一个新的服务配置文件,例如file-sync.service

1
sudo nano /etc/systemd/system/file-sync.service

在打开的文件中,添加以下内容:

1
2
3
4
5
6
7
8
9
10
[Unit]
Description=File Synchronization Service
After=network.target

[Service]
User=your_username
ExecStart=/usr/bin/python3 /path/to/your_script.py

[Install]
WantedBy=default.target

请确保按照实际情况修改以下内容:

  • Description:描述服务的信息。
  • User:你希望该服务以哪个用户身份运行,将your_username替换为你的用户名。
  • ExecStart:指定要运行的Python解释器路径和你的同步脚本的路径。
  1. 保存并关闭文件。

按下Ctrl + X,然后按下Y,最后按下Enter来保存并关闭文件。

  1. 启用并启动服务。

执行以下命令启用并启动服务:

1
2
sudo systemctl enable file-sync.service
sudo systemctl start file-sync.service

这将会启用该服务,并立即启动它。

  1. 验证服务状态。

你可以执行以下命令来验证服务的状态:

1
sudo systemctl status file-sync.service

如果一切正常,你应该能够看到服务正在运行。

  1. 开机自启动设置。

要让该服务在系统开机时自动启动,执行以下命令:

1
sudo systemctl enable file-sync.service

这将会在系统开机时自动启动该服务。

现在,你的同步脚本已经作为一个守护进程运行,并实现了开机自启动。你可以根据需要对脚本和服务进行调整和管理。

scheduler.add_job解析

根据您提供的代码片段,看起来您正在使用一个调度程序(scheduler)来执行名为sync_files的函数。scheduler.add_job()函数用于向调度程序添加一个任务,并指定任务的执行方式和参数。

具体来说,add_job()函数的参数解析如下:

  1. 第一个参数 (sync_files) 是要执行的函数或方法的名称或引用。这是您希望调度程序定期执行的任务。

  2. 第二个参数 ('interval') 是触发器的类型。在这种情况下,您使用了'interval'触发器,它会在指定的时间间隔内重复执行任务。

  3. seconds=30是一个关键字参数,用于指定触发器的时间间隔。在这里,任务将每隔30秒执行一次。

综上所述,您的代码片段将会向调度程序添加一个任务,该任务是定期(每隔30秒)执行名为sync_files的函数。请注意,这只是调度程序的一部分,您可能还需要其他代码来实际启动和运行调度程序。

触发器类型

在调度程序中,常见的触发器类型有以下几种:

  1. date(日期触发器):在指定的日期和时间执行一次任务。

  2. interval(间隔触发器):在指定的时间间隔内重复执行任务。

  3. cron(Cron触发器):根据Cron表达式设置任务执行的时间计划。Cron表达式可以非常灵活地定义任务执行的时间,包括分钟、小时、日期、月份和星期几等。

  4. trigger(自定义触发器):您可以创建自定义的触发器类来满足特定的调度需求。

这些触发器类型为任务的执行提供了不同的时间安排方式,使您能够根据具体需求来安排任务的执行。您可以根据任务的执行频率、时间间隔或特定日期/时间来选择适合的触发器类型。

触发器类型举例

当使用调度程序时,以下是不同类型的触发器的示例:

  1. date 触发器示例:

    1
    scheduler.add_job(my_function, 'date', run_date=datetime(2023, 5, 10, 8, 30, 0))

    上述示例中,my_function 函数将在 2023 年 5 月 10 日 8:30:00 执行一次。

  2. interval 触发器示例:

    1
    scheduler.add_job(my_function, 'interval', seconds=60)

    上述示例中,my_function 函数将每隔 60 秒执行一次。

  3. cron 触发器示例:

    1
    scheduler.add_job(my_function, 'cron', minute='*/15', hour='9-17', day_of_week='mon-fri')

    上述示例中,my_function 函数将在每小时的每隔 15 分钟执行一次,从周一到周五的 9 点到 17 点之间。

  4. 自定义触发器示例:
    您可以根据自己的需求创建自定义的触发器类,这里只展示一个简单的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class MyCustomTrigger:
    def __init__(self, some_parameter):
    self.parameter = some_parameter

    def get_next_run_time(self, previous_run_time):
    # 自定义计算下一次运行时间的逻辑
    # 返回下一次运行时间的 datetime 对象

    # 使用自定义触发器
    my_trigger = MyCustomTrigger(some_value)
    scheduler.add_job(my_function, my_trigger)

    上述示例中,您可以创建一个自定义的触发器类MyCustomTrigger,根据自己的逻辑计算下一次运行时间,并将其传递给调度程序的 add_job() 方法。

这些示例涵盖了常见的触发器类型,您可以根据自己的需求选择适合的触发器类型,并根据触发器的参数进行调整。