尽管以下命令返回取决于远程文件是否存在的退出状态:
ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile
lsReturnValue=$?
然后我可以测试做一些事情,它有时挂起(十分之一或 20)并阻止进一步的代码执行。
所以我需要运行一个像这样的 ssh 命令并检索 ls 函数的退出值:
(ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile ; lsReturnValue=$?) &
timeOutProcess $!
但是,lsReturnValue 始终返回空字符串。
timeOutProcess 是一个函数,如果命令持续时间过长,它会终止我的命令:
timeOutProcess() {
processId=$1
#from http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3
timeout=45
interval=2
delay=5
(
((t = timeout))
while ((t > 0)); do
sleep $interval
kill -0 $processId || return 0
((t -= interval))
done
# Be nice, post SIGTERM first.
# The 'exit 0' below will be executed if any preceeding command fails.
kill -s SIGTERM $processId && kill -0 $processId || exit 0
sleep $delay
kill -s SIGKILL $processId
) 2> /dev/null
}
我想知道我怎样才能得到$? ssh 命令的值?
答案1
您可以通过两种方式使用标准 shell 功能获取进程的返回状态ssh
:同步运行它,或者调用wait
内置函数。当你跑步时
(ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile ; lsReturnValue=$?) &
这只lsReturnValue
在子 shell 中设置,除了返回父 shell 的返回状态之外,您无法获取任何信息。因此,您必须exit $lsReturnValue
从子 shell 运行并从父 shell 获取子 shell 的返回状态;然后整个后台过程可以简化为ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile &
无论如何。
您发现允许命令超时的这个 shell 片段并不是一个很好的片段,因为它不保留返回状态。在 Linux 上,使用timeout
公用事业。
如果没有timeout
实用程序,事情就会变得有点棘手。您需要运行两个子进程:一个是您感兴趣的子进程,另一个是sleep
针对超时部分运行的子进程。如果任一进程返回,它必须杀死另一个进程并允许 shell 继续执行。不幸的是,wait
当您不带参数调用它时,内置函数会等待所有子进程都终止。同步两个进程的一种方法是让它们都写入管道,并在管道上出现一些数据时终止它们。
lsReturnValue=$(
{
{ ssh $userAtServer "ls $targetDir/$targetFile" > $sshOutputFile
echo $?; } &
{ sleep 5; echo timeout; } &
} | head -n 1)
if [ "$lsReturnValue" = "timeout" ]; then …
如果您要向多个服务器发送命令,请认真考虑使用ssh多服务器框架例如 mussh、clustersh 等。
答案2
您的命令有时会被挂起,因为 OpenSSH 功能会阻止 SSH 会话关闭,直到 SSH 会话中运行的进程打开的所有 IO 都正确关闭为止。
防止这种情况的一种方法是将 STDIN 和 STDOUT 重定向到终端以外的其他位置。
ssh $userAtServer "ls $targetDir/$targetFile > /dev/null < /dev/null 2>&1"
# lsReturnValue=$?
如果您需要命令的 STDOUT/STDERR,您可以将它们重定向到文件并稍后对其进行 cat
ssh $userAtServer "ls $targetDir/$targetFile > /tmp/ls_output < /dev/null 2>&1;cat /tmp/ls_output"