想象一下我们有一个很长的命令sleep 10
(例如)。我们想使用 python(paramiko
具体来说是 ssh 库)在另一台服务器上执行它。
我需要一个 1 行命令来启动命令,打印命令的 PID,然后等待它完成,最后返回命令的退出状态。
到目前为止我尝试过的:
bash -c "echo $BASHPID ; exec sleep 10" ; echo $?
这会打印 shell 的 PID,然后对长命令调用 exec,然后等待并打印退出状态。问题是$BASHPID
打印外部 bash shell 的 PID(可能表明调用bash -c cmd
实际上并没有生成一个完整的新 shell?)。
如果我用三行调用上面的命令,它就可以工作。
bash
echo $BASHPID ; exec sleep 10
echo $?
任何使用子外壳的尝试对我来说都不起作用。
echo $(echo $BASHPID ; exec sleep 10) ; echo $?
这是可行的,但是子 shell 将其所有输出通过管道传递给 echo,并且 echo 会立即打印所有内容,这意味着$BASHPID
直到睡眠完成后才会打印。 PID 必须立即打印。
答案1
当你跑步时,例如:
bash -c“回显$BASHPID;执行睡眠10”
或者
回声 $(回声 $BASHPID ; 执行睡眠 10)
$BASHPID
您当前的 shell正在第二个 bash(或子 shell)看到该变量之前插入该变量。解决方案是防止当前 shell 扩展这些变量:
bash -c 'echo $BASHPID ; exec sleep 10'
答案2
这是您已经运行过的 shell 命令ssh
(由远程用户的登录 shell 解释),无需在此基础上启动另一个 shell。假设 shell 是类似 Bourne 或类似 csh 的:
echo "$$"; exec sleep 10
应该足够了。无需bash
在远程主机上安装。ssh
还会报告远程命令的退出状态,无需打印。但如果必须的话,你可以这样做:
sleep 10 & echo "$!"; wait; echo "$?"
$?
不适用于类似 csh 的 shell $status
。
如果您不能保证远程用户的登录 shell 与 Bourne 类似,您可以这样做:
exec sh -c 'sleep 10 & echo "$!"; wait; echo "$?"'
该命令至少应该与 Bourne、csh 和 rc 系列的 shell 兼容。