You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Cron作业脚本产生孤立的ssh-agent进程?

解决Cron脚本中ssh-agent进程残留的问题

问题原因

你的脚本每次通过Cron执行时,因为Cron的运行环境不继承SSH相关环境变量(SSH_AUTH_SOCK为空),所以每次都会启动新的ssh-agent进程,但脚本执行完毕后没有主动终止这个进程,导致大量孤立进程堆积。

解决方案

下面提供几种适合你的修改方案,按复杂度从低到高排序:


方案1:脚本结束时强制杀掉启动的ssh-agent

这是最简单的修改方式,只需要在脚本中添加“退出时清理进程”的逻辑,确保不管脚本成功还是失败,都会杀掉我们启动的ssh-agent。

修改后的run.sh脚本:

#!/bin/sh

# 保存启动的ssh-agent PID,用于后续清理
agent_pid=""

if [ -z "$SSH_AUTH_SOCK" ] ; then
    # 捕获ssh-agent的输出,避免直接eval导致无法提取PID
    agent_output=$(ssh-agent -s)
    eval "$agent_output"
    # 从输出中提取agent的PID
    agent_pid=$(echo "$agent_output" | grep -o "SSH_AGENT_PID=[0-9]*" | cut -d= -f2)
    ssh-add ~/.ssh/remote_backups
fi

# 设置陷阱:脚本退出时(无论正常/异常),杀掉我们启动的ssh-agent
trap '[ -n "$agent_pid" ] && ssh-agent -k' EXIT

# 以下为原有业务代码,无需修改
printf "\n======\n"
date
printf "|| Beginning backup replication...\n"

cd /var/www/html/wp-content/uploads/backups

echo "|| Transferring daily backups..."

lftp sftp://remote_backups <<EOF
cd /home/web/
mirror --exclude=.* --include=./*.zip --include=./*dat ./ backups --delete --reverse --only-newer -v
bye
EOF

cd ../backups-weekly

echo "|| Transferring weekly backups..."
lftp sftp://remote_backups <<EOF
cd /home/web/
mirror --exclude=.* --include=./*.zip ./ backups-weekly --delete --reverse --only-newer -v
bye
EOF

now=$(date)

echo "|| Backup replication complete!"
echo "|| Completed at: ${now}"

原理:

  • 用trap命令注册一个脚本退出时的执行动作,确保ssh-agent进程被强制终止
  • 提取ssh-agent的PID,避免误杀其他用户的agent进程

方案2:复用已有的ssh-agent(减少进程创建)

如果希望尽量复用已有的ssh-agent进程,可以通过固定socket文件路径的方式,让脚本检查是否有存活的agent,没有再启动新的。

修改后的脚本片段:

#!/bin/sh

# 固定ssh-agent的socket文件路径
export SSH_AUTH_SOCK="$HOME/.ssh/agent-socket"
export SSH_AGENT_PID="$HOME/.ssh/agent-pid"

# 检查socket是否存在且agent进程存活
if! [ -S "$SSH_AUTH_SOCK" ] ||! kill -0 "$(cat "$SSH_AGENT_PID" 2>/dev/null)" 2>/dev/null; then
    # 启动新的agent,将PID和socket路径写入文件
    ssh-agent -s | grep -E "(SSH_AUTH_SOCK|SSH_AGENT_PID)" > "$HOME/.ssh/agent-info"
   . "$HOME/.ssh/agent-info"
    ssh-add ~/.ssh/remote_backups
fi

# 后面的业务代码不变...

注意:需要确保~/.ssh目录权限正确(chmod 700 ~/.ssh),避免其他用户访问socket文件。


方案3:彻底抛弃ssh-agent(最省心)

既然你用lftp做SFTP传输,可以直接让lftp指定密钥文件,完全不需要ssh-agent,从根源上解决进程残留问题。

修改脚本中的lftp调用部分,比如将原来的:

lftp sftp://remote_backups <<EOF
cd /home/web/
mirror --exclude=.* --include=./*.zip --include=./*dat ./ backups --delete --reverse --only-newer -v
bye
EOF

替换为:

lftp -e "set sftp:connect-program 'ssh -i ~/.ssh/remote_backups'; cd /home/web/; mirror --exclude=.* --include=./*.zip --include=./*dat ./ backups --delete --reverse --only-newer -v; bye" sftp://remote_backups

然后删除脚本中所有和ssh-agent、ssh-add相关的代码即可。

原理:直接告诉ssh(lftp底层调用的是ssh)使用指定的密钥文件,不需要通过agent来管理密钥,流程更简单,也没有进程残留的风险。

推荐选择

如果你对Linux进程管理不太熟悉,方案3是最省心的,不需要处理agent的生命周期,修改量也小,适合快速解决问题。

内容的提问来源于stack exchange,提问作者Aaron Silber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:01:24