如何正确获取远程脚本PID并传入tail命令的--pid参数?
解决远程启动脚本并实时跟踪日志的PID问题
我明白你的需求——要在脚本里自动远程启动showdigits.sh,然后精准获取它的PID来让tail实时跟踪日志,直到脚本结束。你之前遇到的问题主要是PID匹配不准确、本地/远程变量解析冲突导致的,下面给你几个简洁可靠的解决方案:
方案1:单SSH会话完成所有操作(最推荐)
把启动脚本、获取PID、跟踪日志的操作放在同一个远程shell会话里,这样所有变量都是远程环境的,不会有本地解析的问题,而且能直接拿到刚启动进程的准确PID:
ssh user@host 'nohup sh showdigits.sh & echo $! > showdigits.pid && tail --pid=$(cat showdigits.pid) -f logs'
为什么这个能行?
nohup sh showdigits.sh &后台启动脚本后,$!是远程shell里刚启动的后台进程的PID,这是最准确的,不会匹配到其他无关进程。- 把PID写入文件后,
tail --pid=$(cat showdigits.pid)直接读取这个PID,确保只跟踪目标进程,不会出现多PID的问题。
方案2:分两次SSH会话,PID传递到本地
如果需要把启动和跟踪日志的操作分开(比如中间要做其他操作),可以先远程启动脚本并把PID返回本地,再用这个PID发起跟踪:
# 第一步:远程启动脚本,获取PID并传回本地 REMOTE_PID=$(ssh user@host 'nohup sh showdigits.sh & echo $!') # 第二步:用拿到的PID远程跟踪日志 ssh user@host "tail --pid=$REMOTE_PID -f logs"
解决你之前的错误点:
- 多PID问题:你之前用
pgrep -f showdigits.sh会匹配到pgrep命令本身(因为命令行里包含showdigits.sh),导致拿到多个PID。用$!直接获取刚启动进程的PID是最精准的方式。 - 变量解析冲突:你第二个尝试里用了双引号,其中的
cat pid是本地shell执行的(而pid文件在远程服务器),所以报错找不到文件。同时awk '/[s]howdigits.sh/{print $2}'里的$2被本地shell解析了,应该用单引号包裹awk命令,或者转义$为\$2——不过用$!比pgrep/awk的方式更简单可靠。
额外提示
如果showdigits.sh启动后会fork子进程,那$!拿到的是父进程PID,这时候需要调整获取子进程的方式,但根据你的描述,脚本是直接写入日志并休眠,应该不会fork,所以上面的方案完全适用。
内容的提问来源于stack exchange,提问作者Leonald
相关产品推荐
相关产品推荐

