23

在 shell 脚本的循环中,我连接到各种服务器并运行一些命令。例如

#!/bin/bash
FILENAME=$1
cat $FILENAME | while read HOST
do
   0</dev/null ssh $HOST 'echo password| sudo -S 
   echo $HOST 
   echo $?      
   pwd
   echo $?'
done

在这里,我正在运行“echo $HOST”和“pwd”命令,并且通过“echo $?”获得退出状态。

我的问题是我希望能够将远程运行的命令的退出状态存储在某个变量中,然后(基于命令是否成功)将日志写入本地文件。

任何帮助和代码表示赞赏。

4

4 回答 4

37

ssh将使用远程命令的退出代码退出。例如:

$ ssh localhost exit 10
$ echo $?
10

因此,在您的ssh命令退出后,您可以简单地检查$?. 您需要确保不掩盖您的返回值。例如,您的 ssh 命令以以下方式结束:

echo $?

这将始终返回 0。您可能想要的是更像这样的东西:

while read HOST; do
  echo $HOST
  if ssh $HOST 'somecommand' < /dev/null; then
    echo SUCCESS
  else
    echo FAIL
done

你也可以这样写:

while read HOST; do
  echo $HOST
  if ssh $HOST 'somecommand' < /dev/null
  if [ $? -eq 0 ]; then
    echo SUCCESS
  else
    echo FAIL
done
于 2013-03-13T16:50:37.443 回答
2

您可以将退出状态分配给变量,如下所示:

variable=$?

在您尝试检查的命令之后。不要echo $?之前或新的值$?将是退出代码echo(通常为0)。

于 2016-06-02T18:14:34.883 回答
0

一种有趣的方法是使用反引号检索在局部变量中设置的每个 ssh 命令的全部输出,或者甚至使用特殊字符(为简单起见说“:”)分开,例如:

export MYVAR=`ssh $HOST 'echo -n ${HOSTNAME}\:;pwd'`

在此之后,您可以使用awk拆分MYVAR为您的结果并继续 bash 测试。

于 2013-03-13T17:46:16.803 回答
0

也许在另一边准备日志文件并将其通过管道传输到标准输出,如下所示:

ssh -n user@example.com 'x() { local ret; "$@" >&2; ret=$?; echo "[`date +%Y%m%d-%H%M%S` $ret] $*"; return $ret; };
x true
x false
x sh -c "exit 77";'  > local-logfile 

基本上,只需在要使用此x包装器调用的遥控器上添加所有内容的前缀即可。它也适用于条件,因为它不会改变命令的退出代码。

您可以轻松循环此命令。

此示例将类似以下内容写入日志:

[20141218-174611 0] true
[20141218-174611 1] false
[20141218-174611 77] sh -c exit 77

当然,您可以使其更好地解析或根据您的喜好调整日志文件的外观。请注意,远程程序的未捕获法线stdout被写入stderr(请参阅 中的重定向x())。

如果您需要一个配方来捕捉和准备日志文件的命令输出,这里是来自https://gist.github.com/hilbix/c53d525f113df77e323d的此类捕捉器的副本- 但是是的,这是一个更大的样板文件“在 shell 的当前上下文中运行某些东西,后处理 stdout+stderr 而不会干扰返回代码”:

# Redirect lines of stdin/stdout to some other function
# outfn and errfn get following arguments
# "cmd args.." "one line full of output"
: catch outfn errfn cmd args..
catch()
{
local ret o1 o2 tmp
tmp=$(mktemp "catch_XXXXXXX.tmp")
mkfifo "$tmp.out"
mkfifo "$tmp.err"
pipestdinto "$1" "${*:3}" <"$tmp.out" &
o1=$!
pipestdinto "$2" "${*:3}" <"$tmp.err" &
o2=$!
"${@:3}" >"$tmp.out" 2>"$tmp.err"
ret=$?
rm -f "$tmp.out" "$tmp.err" "$tmp"
wait $o1
wait $o2
return $ret
}

: pipestdinto cmd args..
pipestdinto()
{
local x
while read -r x; do "$@" "$x" </dev/null; done
}

STAMP()
{
date +%Y%m%d-%H%M%S
}

# example output function
NOTE()
{
echo "NOTE `STAMP`: $*"
}

ERR()
{
echo "ERR `STAMP`: $*" >&2
}

catch_example()
{
# Example use
catch NOTE ERR find /proc -ls
}

有关示例,请参见倒数第二行(向下滚动)

于 2014-12-18T17:01:32.497 回答