将命令的输出保存在数组中

将命令的输出保存在数组中

我正在执行这个命令

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)来解释命令行。为此,它连接了参数。因此,最终在您的方法中运行的是带有-csh -c id;whoami;ps aux作为参数的 shell,然后该 shell 将运行sh -c id,whoamips aux。在这里是sh -c多余的,只会造成混乱。

请注意,数组元素将包含每个命令的完整输出,包括尾随换行符。

如果您想打印它们,请使用:

printf %s "$id_output"

要删除换行符,您可以执行以下操作:

id_output=${id_output%$'\n'}

答案2

您的命令将 ssh 命令的每个以空格分隔的字符串存储在一个数组中。所以,既然你正在 ssh 然后运行idwhoami并且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是最小的。

相关内容