我正在执行这个命令
ar=($( ssh -i id_rsa -T -y [email protected] sh -c "id;whoami;ps aux"))
ps aux
我需要将执行的每个命令的输出保存到数组中并调用该数组,但是在调用数组时我无法获得所需的结果或其他命令
echo ${ar[2]}
它只是向我展示了 ps aux 的第一行,即
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
而不是完整的结果ps aux
答案1
尝试一下(bash4.4+)
readarray -td '' a < <(
ssh -i id_rsa -T -y [email protected] '
id; printf "\0"
whoami; printf "\0"
ps aux; printf "\0"'
)
id_output=${a[0]}
whoami_output=${a[1]}
ps_output=${a[2]}
ssh
已经调用 shell(该root
用户的登录 shell)来解释命令行。为此,它连接了参数。因此,最终在您的方法中运行的是带有-c
和sh -c id;whoami;ps aux
作为参数的 shell,然后该 shell 将运行sh -c id
,whoami
和ps aux
。在这里是sh -c
多余的,只会造成混乱。
请注意,数组元素将包含每个命令的完整输出,包括尾随换行符。
如果您想打印它们,请使用:
printf %s "$id_output"
要删除换行符,您可以执行以下操作:
id_output=${id_output%$'\n'}
答案2
您的命令将 ssh 命令的每个以空格分隔的字符串存储在一个数组中。所以,既然你正在 ssh 然后运行id
,whoami
并且ps aux
,全部它们的输出被添加到数组中,并按空格($IFS
变量的默认值)进行分割。您可以使用以下命令查看declare -p ar
:
$ ar=($( ssh localhost sh -c "id;whoami;ps aux"))
$ declare -p ar | head -c500
declare -a ar=([0]="uid=1000(terdon)" [1]="gid=1000(terdon)" [2]="groups=1000(terdon),3(sys),7(lp),10(wheel),14(uucp),56(bumblebee),84(avahi),96(scanner),209(cups),995(plugdev)" [3]="terdon" [4]="USER" [5]="PID" [6]="%CPU" [7]="%MEM" [8]="VSZ" [9]="RSS" [10]="TTY" [11]="STAT" [12]="START" [13]="TIME" [14]="COMMAND" [15]="root" [16]="1" [17]="0.0" [18]="0.0" [19]="174456" [20]="11996" [21]="a" [22]="b" [23]="f" [24]="R" [25]="Ss" [26]="Jun23" [27]="7:06" [28]="/sbin/init" [29]="root" [30]="2"
正如您所看到的,每个命令运行的输出的每个以空格分隔的字符串都存储在其自己的数组元素中。
如果您想要一个仅包含三个元素的数组,每个命令一个元素,则需要使用不同的字符进行拆分。实现此目的的一种方法是编辑命令,以便它们在执行后打印唯一字符,然后用于mapfile
读取数组,告诉它在该唯一字符上进行拆分。例如,\0
:
$ mapfile -d '' < <( ssh localhost sh -c "id; printf '\0'; whoami; printf '\0'; ps aux") ar
$ for i in 0 1 2; do echo "$i: ${ar[i]}"; done | head
0: uid=1000(terdon) gid=1000(terdon) groups=1000(terdon),3(sys),7(lp),10(wheel),14(uucp),56(bumblebee),84(avahi),96(scanner),209(cups),995(plugdev)
1: terdon
2: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 174456 11996 ? Ss Jun23 7:07 /sbin/init
root 2 0.0 0.0 0 0 ? S Jun23 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< Jun23 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< Jun23 0:00 [rcu_par_gp]
root 6 0.0 0.0 0 0 ? I< Jun23 0:00 [kworker/0:0H-kblockd]
答案3
昂贵的部分ssh
是身份验证过程。我将使用该ControlMaster
选项来允许多个单独的ssh
会话共享单个经过身份验证的连接。
ssh_get () {
ssh -o ControlMaster=auto -o ControlPersist=5 -i id_rsa -T -y [email protected] "$@"
}
for cmd in id whoami "ps aux"; do
ar+=("$(ssh_get "$cmd")")
done
第一个调用将进行身份验证,但退出后,连接ssh
将在后台保留最多 5 秒(根据选项ControlPersist
),允许下一个调用使用它而无需重新身份验证。运行本身的开销ssh
是最小的。