Bashから渡された変数の評価

Bashから渡された変数の評価

変数をbashスクリプトにパラメータとして渡し、bashスクリプトで評価する方法はありますか?

与えられた:

# cat /path/to/file/of/host/names
bob
tom
joe
etc...


# dofor
FILE=$1
shift
CMD=$*

while read host; do
    # recursively turns "ssh \$host hostname" from $@ into:
    # ssh bob hostname
    # ssh tom hostname
    # ssh joe hostname
    # etc...
    eval $CMD
done < $FILE

いつ:

# dofor /path/to/file/of/host/names "ssh \$host hostname"

それからssh host hostname:/path/to/file/of/host/namesにリストされている各ホスト名に対して実行結果を受け取ります。たとえば、

bob.example.com
tom.example.com
joe.example.com
etc...

答え1

この試み:

#!/bin/bash

FILE=$1
shift
CMD=$*
cmds=""

source <({
cat $FILE | while read host; do
    echo $CMD | sed -e "s|\$host|$host|g"
done
})

答え2

あなたはそれを使用することができます

#!/bin/bash
FILE=$1
exec 3<$FILE
while read -u 3 host; do
    $2 $host $3
done

したがって、次のような場合:

$ cat /tmp/hostnames
some.host1.com
another.host2.net
some.host3.org    
some.host4.com

その後、実行するとdofor.sh /tmp/hostnames ssh ls順番に実行されます。

ssh some.host1.com ls
ssh another.host2.net ls
ssh some.host3.org ls
ssh some.host4.com ls

編集1:

より長いコマンド(またはその一部)を変更するには、引用符を使用sshしてください。ls

dofor.sh /tmp/hostnames "ssh -p 23" "ls -lh /"

編集2:

次のスクリプトを使用すると、$hostコマンドの任意の場所で変数を使用できます。

#!/bin/bash
exec 3<$1
while read -u 3 host; do
    eval $2
done

(私はこれを短縮しました - 役に立たない$FILE変数は導入されませんでした。)ここで重要な部分はアポストロフィ$host 変数を含むコマンドの周辺:

 dofor.sh /tmp/hostnames 'echo "trying $host :"; ssh -p 23 myuser@$host "ls -lh /"'

しかし、警戒する使用するのは危険ですeval(参照l0b0の壁)ファイルの特定/tmp/hostnamesの行にコマンドが含まれている場合は、そのコマンドが実行されるためです。として使用しないことをお勧めしますroot

答え3

これはうまくいきますが、本物コンテンツを完全に制御できない場合は悪い考えです。$FILE そしてこれには非常に簡単な文だけが含まれています。

while read -r
do
    $REPLY
done < $FILE

SSHの例では、ホスト名を繰り返してより簡単な操作を実行できます。

while read -r host
do
    echo -n "${host}:"
    ssh "$host" hostname
done 9< "$FILE"

my hostname:remote hostnameアイテムのリストを返す必要があります。

実際のコマンドを含むファイルがある場合は、スペースが正しく処理されていることを確認する必要があります。それを処理する唯一の方法はどのパラメータ(たとえば、echo複数のパラメータを持つコマンドを含む)はカスタム形式を使用します。比較的簡単な方法は、各コマンドと引数を␀文字で区切って、コマンドの最後の引数と次のコマンドの間に追加の␀文字を配置することです。

関連情報