コマンドの出力を配列に保存する

コマンドの出力を配列に保存する

このコマンドを実行しています。

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]}

sshrootコマンドラインを解釈するためにシェル(このユーザーのログインシェル)が呼び出されました。これを行うには、パラメータをリンクします。したがって、メソッドで実行されるのはおよび引数の-cあるシェルであり、そのシェルは、およびをsh -c id;whoami;ps aux実行します。ここでは重複して混乱を引き起こすだけです。sh -c idwhoamips auxsh -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" 

ご覧のとおり、各コマンド実行でスペースで区切られた各出力文字列は、独自の配列要素に格納されます。

各コマンドごとに1つずつ、3つの要素のみを持つ配列が必要な場合は、別の文字を使用して分割する必要があります。これを達成する1つの方法は、実行後に一意の文字を印刷するようにコマンドを編集し、配列を読み取るために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最小化されます。

関連情報