forループを介してリモートコマンドにSSHを使用することはできません。

forループを介してリモートコマンドにSSHを使用することはできません。

次の for ループを実行しようとしています。

cat  all_data |
  awk '{print $1 " "$2" " $3}'  |
  while read inst type serial ; do
    echo $inst
    if [ `echo ${inst} | cut -d '-' -f2` = H3 ]; then
      ssh  -t  username@hostname3 "sudo ls"
    elif [ `echo ${inst} | cut -d '-' -f2` = H2 ] ; then
      ssh  -t  username@hostname2 "sudo ls"
    elif [ `echo ${inst} | cut -d '-' -f2` = H1 ]; then
      ssh  -t  username@hostname1 "sudo ls"
    fi
  done

ssh -t 部分を実行できません。 stdinが端末ではないため、疑似端末が割り当てられていないとします。 sudo:ttyがなく、Askpassプログラムが指定されていません。 -t -tと-nを試してみましたが、不運です。このコマンドを実行しているホストではvisudoファイルを編集できません。

編集する

$ cat all_data
ABC-DIF2    DELL-800    60999
ABC-DIF3    HP-DL340    J0777
ABC-DIF4    DELL-800    P0087
.
.
.

all_dataには1000の類似アイテムが含まれています。私は以下を試しています。 60999,J0777... は、コマンドの実行に必要なエンティティです。

そのため、各行を読み取り、分割して、そのエンティティに対応するDIF番号が何であるかを確認したいと思います。

たとえば、DIF2を読み取ると、ホスト名2にsshを接続し、コマンドを実行して60999のデータを取得する必要があります。

DIF3 を読み取ると、エンティティ J0777 はホスト名 3 でのみ実行できることを意味します。

答え1

解説者:あなたの(はい?)と役に立たcatないawkので、繰り返してテストする必要はありませんecho|cut

リモートsudoのパスワードを入力する必要があることを明確にした後両方ssh端末を使用して入力し、-t入力がPTYに渡されることを指定します。これは基本的に詐欺です。SSHはwhileループを停止します。同じ症状が現れなくても。

方法1:ループのstdinをリダイレクト(またはパイプ)しますが、リダイレクトします。後ろにSSHの場合

while read inst type serial; do 
  case ${inst#*-} in
  (DIF1) ssh </dev/tty -t user@host1 "sudo blah";;
  (DIF2) ssh </dev/tty -t user@host2 "sudo blech";;
  # more as needed
  esac
done <alldata 
# or cat/awk/whatever | while read ... done

方法2:すべてのデータに異なる単位番号を使用する(標準入力ではありません)

while read <&3 inst type serial; do
  case ${inst#*-} in
  (DIF1) ssh -t user@host1 "sudo blah";;
  (DIF2) ssh -t user@host2 "sudo blech";;
  # more
  esac
done 3<alldata 
# or while read ... done 3< <(cat/awk/whatever) with zsh/bash

方法3は、チャネルなしで引数から読み取るループを使用することですfor(Qではそうしますが、これはしません)。最初に実際に1つのフィールドしか使用していないQの場合、これは簡単です。

IFS='
' # split on newline only
set -o noglob # disable globbing
for inst in $(awk '{print $1}' alldata); do
  # as for method 2
done

しかし、編集者は少なくとも1つの異なるフィールドを使用したいと言っているので、次のようなより厄介なフィールドが必要です。

IFS='
' # split on newline only
set -o noglob # disable globbing
for line in $(awk '{print $1":"$2":"$3}' alldata); do
  IFS=:; set -- $line; inst=$1; serial=$3;
  # as before
done

関連情報