![명령의 출력을 배열에 저장](https://linux55.com/image/176368/%EB%AA%85%EB%A0%B9%EC%9D%98%20%EC%B6%9C%EB%A0%A5%EC%9D%84%20%EB%B0%B0%EC%97%B4%EC%97%90%20%EC%A0%80%EC%9E%A5.png)
이 명령을 실행하고 있어요
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
root
명령줄을 해석하기 위해 쉘(이 사용자의 로그인 쉘) 이 호출되었습니다 . 이를 위해 매개변수를 연결합니다. 따라서 메소드에서 실행되는 것은 -c
및 인수가 있는 쉘이며 , 해당 쉘은 , 및 sh -c id;whoami;ps aux
를 실행합니다 . 여기서는 중복 되어 혼란을 야기할 뿐입니다.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
최소화됩니다.