SSHで`cd`コマンドが機能しないのはなぜですか?

SSHで`cd`コマンドが機能しないのはなぜですか?

SSHを介して一部のファイルをバックアップしようとしていますが、目的のtarファイルをバックアップするのではなく、ホームフォルダがバックアップされます。私はいくつかの追加テストを行いましたが、結果は次のとおりです。

ssh root@server /bin/sh -c "cd /boot && ls -l"

驚くべきことに、ファイルがリストされています。/rootいいえ/boot。ただし、/bin/sh端末で完全なコマンドを実行するとcd正しく機能し、/bootファイルが印刷されます。

ここで何が起こっているのでしょうか?

答え1

sshでは、リモートホストのexecvpに渡される一連の引数と同じくらい正確にコマンドを指定することはできません。代わりに、すべての引数を文字列で連結し、リモートシェルを介して実行します。私の考えでは、これはsshの主な設計上の欠陥です。ほとんどの点でうまく機能するUnixツールですが、コマンドを指定する時が来たら、argvの代わりに単一の単一文字列を使用するように選択します。 MSDOS用に設計されています!

sshはコマンドを単一の文字列として渡すため、sh -c直接提供する必要はありませんsh -c

sh -c '/bin/sh -c cd /boot && ls -l'

元の参照が失われます。したがって、区切り文字を持つコマンドは次&&のようになります。

`/bin/sh -c cd /boot`
`ls -l`

$0最初はコマンドテキスト "cd"と=を使用してシェルを実行します"boot"。 "cd"コマンドは正常に完了し、重要ではなく、$0成功を/bin/sh -cマークしてからls -l発生します。

答え2

引用問題です。 sshはシェルに渡したコマンドを実行しました。複数の引数を渡すと、スペースで連結され、文字列を構成します。したがって、リモートで実行するリモートコマンドは/bin/sh -c cd /boot && ls -l(コマンドの引用符がローカルシェルによって解釈されるため、引用符はありません)です。

/bin/sh -c cd /boot実行し/bin/sh、コマンドを実行して設定するcdよう$0に指示します/boot。完了すると、親シェル(で始まるシェルsshd)が実行されますls -l

あなたの場合、sh -cリモートシェル(/etc/passwdまたは他のパスワードデータベースなど)がこのコマンドを理解していない限り、それらを削除することは完全に役に立ちません。

ssh root@server "cd /boot && ls -l"

別のシェルを呼び出す必要がある場合は、リモートコマンドを引用して呼び出すリモートシェルによって拡張されるのを防ぐ必要がありますsshd。たとえば、ログインシェルがダッシュで bash コマンドを実行したい場合:

ssh root@server 'bash -c "cd ~bob && ls -l"'

答え3

私はこれがシェルがオプションを解析する方法とより関連していると思います。たとえば、次のように動作します。

$ ssh root@server /bin/sh -c '"cd /boot && ls -l"'

これはあなたのコマンドと同じ問題があります。

$ ssh root@server /bin/sh -c 'cd /boot && ls -l'

-vスイッチを有効にすると、ssh何が起こるかを確認できます。

最初のコマンド:

debug1: コマンドの送信: /bin/sh -c "cd /boot && ls -l"

2番目のコマンド:

debug1: コマンドの送信: /bin/sh -c cd /boot && ls -l

通常、コマンドを送信するときは、引用ssh符と引用符内の引用符に特別な注意を払う必要があります。個々のレイヤーからそれを削除するためです。気にしないでください/bin/sh

ssh次の参考資料を理解することで、非常に便利な作業を実行できます。これにより、リモートサーバーでコマンドが実行されますが、sshコマンドが実行されているシステムのローカルファイルに結果が収集されます。

$ ssh root@server 'free -m' > /tmp/memory.status

または、この方法でリモートサーバーのディレクトリを圧縮してローカルシステムに作成します。

$ ssh remotehost 'tar zcvf - SOURCEDIR' | cat > DESTFILE.tar.gz

引用する

答え4

通常、使用するシェルを指定する必要はありません。これは働きます:

ssh user@host "cd /boot && pwd"

ただし、基本シェルに問題がある場合は、次のように引用してください。みんなシェル呼び出しを含むコマンド。次の作品の一つ

ssh user@host '/bin/sh -c "cd /boot && pwd"'
ssh user@host "/bin/sh -c \"cd /boot && pwd\""

関連情報