AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 776530
Accepted
user149408
user149408
Asked: 2024-05-16 00:53:32 +0800 CST2024-05-16 00:53:32 +0800 CST 2024-05-16 00:53:32 +0800 CST

通过 cron Unison,如何处理一项作业在下一项作业开始时仍在运行

  • 772

我有一个设置,其中通过 SSH 连接使用 Unison 在两个 Linux 服务器之间同步文件。这是通过 cron 运行以下命令来实现的:

unison -auto -batch PROFILE

文件集的更改几乎只发生在一侧(另一个系统是异地副本)。它们大多是通过与客户端计算机的另一个 Unison 同步运行(手动触发)进行的,并且间隔时间可能从几个小时到几周不等。因此,两台机器之间的冲突在实践中并不是什么大问题,并且更改传播到另一端的最多 24 小时的延迟是可以接受的。

我将 Unison 作为 cron 作业而不是-repeat(大概作为 systemd 服务)运行的原因是:

  • 可预测的同步时间,因为 cron 作业被安排在我不期望第三台机器进行任何手动同步操作的时间(而,比如说,-repeat 86400会随着同步操作的持续时间而漂移)。
  • 更改主要发生在服务器 A 上,而服务器到服务器同步作业由服务器 B 触发(如果服务器 B 发起连接,网络方面是否更容易)。因此,据我了解,-repeat watch不会接受大部分更改,即使使用-repeat watch+TIME,我也几乎完全依赖TIME(如果我错过了某些内容,请纠正我)。

当变化确实发生时,变化的幅度通常很小。然而,有时,要传输的数据量使得单个 Unison 运行的持续时间是两个 Unison cron 作业之间的间隔的数倍(系统之间的带宽受到一定限制)。这意味着当 cron 在同一组文件上启动下一个进程时,一个 Unison 进程仍在运行。

我认为 Unison 具有锁定机制,这大概可以防止“新”进程干扰“旧”进程正在处理的任何事情(但如果我拧干或遗漏了某些东西,请纠正我)。但我想知道在这种情况下第二个 Unison 进程会做什么 - 我观察到它不会退出而是保留下来。这是否意味着第二个进程将等待第一个进程完成,然后才开始同步(这样将仅包括在第一次同步进行时更改的文件,因此在第一次运行时无法同步)?

当另一个 Unison 进程仍在同一配置文件上运行时启动第二个 Unison 进程是否安全? (如果不是,当且仅当两个并发 Unison 实例存在相互干扰的风险时,建议采用什么方法来阻止它们?)

unison -repeat wait+TIME与偶尔有多个 Unison 实例排队、一个正在运行而其他等待其完成的资源开销又如何呢?

linux
  • 4 4 个回答
  • 653 Views

4 个回答

  • Voted
  1. larsks
    2024-05-16T01:25:28+08:002024-05-16T01:25:28+08:00

    如果您想避免在另一个进程已经运行时启动第二个 unison 实例,您可以通过命令使用锁定文件来控制启动flock。这是一个通用解决方案,它适用于“当另一个实例已经运行时防止第二个实例运行”。

    如果您希望在另一个实例运行时启动失败:

    flock -n /path/to/lockfile unison -auto -batch PROFILE
    

    如果您希望启动阻塞直到现有进程退出:

    flock /path/to/lockfile unison -auto -batch PROFILE
    

    请参阅flock(1)手册页以获取更多信息。

    • 11
  2. Mike Pierce
    2024-05-16T07:15:02+08:002024-05-16T07:15:02+08:00

    Unison(版本 2.51.2)创建自己的锁定文件。刚刚测试它,从命令行运行一致同步两次,第二次是在第一个仍在运行时,我得到了这个错误(带有匿名的内容):

    Failed: Destination updated during synchronization
    The contents of file FOO/BAR.text have been modified
    Failed [FOO/BAR.text]: Destination updated during synchronization
    The contents of file foo/bar.text have been modified
    UNISON 2.51.2 (OCAML 4.05.0) finished propagating changes at 17:08:02.32 on 15 May 2024
    Saving synchronizer state
    Fatal error: Warning: the archives are locked.  
    If no other instance of unison is running, the locks should be removed.
    The file /HOME/ME/.unison/GIANTLONGHASHGIANTLONGHASHBIGYIKES on host LOCALHOST should be deleted
    The file /WHEREVER/.unison/GIANTLONGHASHGIANTLONGHASHBIGYIKES on host REMOTEHOST should be deleted
    Please delete lock files as appropriate and try again.
    

    因此,如果第二个 unison 实例检测到这些锁定文件并推测当前正在运行另一个 unison 同步,那么它似乎将致命退出。

    • 5
  3. Best Answer
    Bob
    2024-05-17T23:30:22+08:002024-05-17T23:30:22+08:00

    我将 Unison 作为 cron 作业而不是使用 -repeat 运行的原因(大概是作为 systemd 服务)

    我实际上建议 systemd 非常适合您想要“cron 但单一实例”的情况。您不需要将其保留为长期运行的服务 - 您可以以类似 cron 的方式使用 systemd 计时器,同时利用 systemd 来管理实例。

    1. 定义 的 systemd 服务Type=exec。在进程退出之前,该服务将被视为活动的。使用当前与 cron 相同的命令行。
    2. 定义一个 systemd 计时器来启动之前定义的服务。这可以设置为在时钟(日历)时间 ( OnCalendar=) 或一段时间后发生(OnUnitActiveSec=相对于上次服务启动时间,OnUnitInactiveSec=相对于上次服务停止时间)。就我个人而言,我喜欢日历,因为它更可预测并且不会漂移。
    3. 启用并启动计时器。不要启用该服务,您不希望它独立于计时器运行。
    4. 计时器将按计划启动服务。服务管理器将确保该服务只有一个实例处于活动状态。如果下次计时器触发时服务仍在运行,它将不会执行任何操作。

    以 SOMEUSER 身份使用配置文件 SOMEPROFILE 运行 Unison 的示例单元文件(除了它们的.service和.timer后缀外,两个单元文件必须具有相同的名称):

    unison.service:

    [Unit]
    Description=Unison SOMEUSER@SOMEPROFILE
    After=network.target
    
    [Service]
    User=SOMEUSER
    # Type=simple may be used on older versions
    Type=exec
    # may be relative to the service's root directory specified by RootDirectory=, or the special value "~"
    WorkingDirectory=~
    # systemd may insist on an absolute path for the executable
    # Run unison with -terse to prevent cluttering the system journal
    ExecStart=/usr/bin/unison -auto -batch -ui text -terse SOMEPROFILE
    Restart=no
    

    unison.timer(每天 13:37 触发;有关OnCalendar语法man 5 systemd.time,请参阅日历事件部分):

    [Unit]
    Description=Daily unison SOMEUSER@SOMEPROFILE
    
    [Timer]
    OnCalendar=*-*-* 13:37
    
    [Install]
    WantedBy=timers.target
    

    将这两个单元文件放入/etc/systemd/system/,然后运行:

    sudo systemctl enable unison.timer
    sudo systemctl start unison.timer
    

    您可以通过运行来测试设置sudo systemctl start unison.service- 这仅需要服务单元,而不需要计时器单元。这也是一种不按计划开始同步的方法。 Unison 输出将unison作为标签写入系统日志。

    • 2
  4. Sotto Voce
    2024-05-17T07:55:45+08:002024-05-17T07:55:45+08:00

    我还在flockcron 作业 shell 脚本中使用以避免一次运行多个任务。我使用的方法与之前答案中建议的方法不同。我将展示代码并描述其优点/缺点。

    Bash 代码片段,只需稍作更改即可在其他 shell 中使用:

    script_name='my-cron-command'
    lock_file="/tmp/${script_name}.lock"
    
    # this flock solution uses a subshell
    (
      # get a lock on subshell's file descriptor 300 (see below)
        flock -x -n 300 || {
        echo "${script name}: Warning: cannot get lock on file ${lock_file}.  Exiting..." >&2
        exit 0
      }
    
      # lock was successful, okay to run my command
    
      ### command here ###
    
      # subshell's file descriptor 300 is open on the lockfile
    ) 300>"${lock_file}"
    

    缺点:

    • 该脚本不会等到前一个脚本释放锁。
    • 调用额外的子shell进程。

    好处:

    • 一项挂起的 cron 作业不会导致后续作业累积等待锁、增加进程列表和消耗 RAM。
    • 当子 shell 退出时,锁被释放。不需要命令来解锁文件,并且崩溃的命令/脚本不会留下陈旧的锁。 (可以使用 找到挂起的命令fuser /path/to/lock.file)
    • 当锁定文件已被锁定时,脚本可以在退出之前记录一条有意义的消息。
    • 不限于仅锁定一个命令。该脚本可以在获取锁和运行命令之间执行其他文件/变量操作。

    文件描述符 300 并不特殊,它只是一个高编号描述符,不太可能被脚本的其他部分使用。

    与其他一切一样,这是您想要的行为和您不想要的行为之间的权衡。

    • 0

相关问题

  • 有没有办法让 ls 只显示某些目录的隐藏文件?

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve