任意引数処理情報

任意引数処理情報

ローカルで実行すると正しく動作するスクリプトを作成しました。

./sysMole -time Aug 18 18

議論「-時間」「八月」「18」「18」正常にスクリプトに渡されました。

これで、スクリプトはリモートシステムで実行されますが、ローカルシステムのローカルディレクトリで実行するように設計されています。例:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole

これも素晴らしい作品です。しかし、上記の主張を含めようとすると問題が発生します。(-時間2018年8月18日)、例えば:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18

スクリプトを実行した後、次のエラーが発生します。

bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell

何が間違っているのか教えてください。とても残念です。

答え1

あなたの例は非常に近いです。これらのパラメータと組み合わせて使用​​すると、非常にうまく機能します。

スクリプト例:

$ more ex.bash 
#!/bin/bash

echo $1 $2

有効な例:

$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye

ただし、次の型の引数では失敗します。

$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...

どうなりますか?

あなたが経験している問題は、パラメータにあるか、-time私の--time例ではに切り替えると解釈されることですbash -sbash引数で終了して残りのコマンドライン引数を取得すると、それを変更できます--

このように:

$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18

はい

#1:

$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye

#2:

$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye

#サム:

$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye

#4:

$ ssh  < ./ex.bash serverA "bash -s -- --time bye"
--time bye

メモ:明らかに、コマンドラインにリダイレクトが表示されるたびに違いはありません。sshリモートシェルはとにかくその引数を連結して呼び出されるため、リモートシェルから引用する必要がない限り、引用は大きな違いを生じません。例えば#4:

$ ssh  < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>

答え2

任意引数処理情報

実際には単一の文字列のみを使用する場合、つまり。-time Aug 18 18では、簡単にハードコーディングすることができ、既存の回答を使って適切に行う方法がわかります。一方、未知のパラメータ(他のシステムに表示するメッセージ、またはエンドユーザーがその名前を制御できる生成されたファイル名)を渡す必要がある場合は、さらに注意する必要があります。


bash~kshとともに/bin/sh

リモートが/bin/shbashまたはkshによって提供されている場合、信頼できない引数のリストを使用して以下を安全に実行できるため、悪意のある名前(たとえば$(rm -rf $HOME).txt)も安全に引数として渡される可能性があります。

runRemote() {
  local args script

  script=$1; shift

  # generate eval-safe quoted version of current argument list
  printf -v args '%q ' "$@"

  # pass that through on the command line to bash -s
  # note that $args is parsed remotely by /bin/sh, not by bash!
  ssh user@remote-addr "bash -s -- $args" < "$script"
}

すべてのPOSIXと互換性があります/bin/sh

printf %q十分に悪意のある引数データ(エスケープされた文字列に印刷できない文字があるときにbashで使用される非POSIX準拠の引用符を利用しようとするなど)から安全にするには、デフォルトの/bin/shPOSIX(たとえばdashash

runRemote() {
  local script=$1; shift
  local args
  printf -v args '%q ' "$@"
  ssh user@remote-addr "bash -s" <<EOF

  # pass quoted arguments through for parsing by remote bash
  set -- $args

  # substitute literal script text into heredoc
  $(< "$script")

EOF
}

使用法(上記のいずれかの状況に適用可能)

その後、上記の関数を呼び出すことができます。

# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18

...または...

# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"

答え3

次のようにコマンドを引用符で囲みます。

ssh myserver "date +\"Date: %Y%m%d %H:%M\";printf \"Uptime: \";uptime;printf \"uname: \";uname -a"
Date: 20200409 20:02
Uptime:  20:02:29 up 66 days, 55 min,  2 users,  load average: 0.06, 0.05, 0.08
uname: Linux zltcmtn23aecc1rx7322 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Connection to 105.31.182.217 closed.

答え4

aaがlsを含むローカルファイルであるとします。

$ssh servername "cat | bash" < a.a

127.0.0.1をリモートIPアドレスに変更します。

これらの2つは、偽のtty割り当てに関するメッセージを提供しますが、動作します。

$ cat a.a | ssh 127.0.0.1

$ ssh 127.0.0.1 <a.a

または

$ cat a.a | ssh 127.0.0.1 bash or

$ ssh 127.0.0.1 bash < a.a

関連情報