1

Gentoo Linux の wiki で、動的 jumphost リストに関する次の記述に出くわしました。

    ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') nc -w1 $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /')

sed動作しますが、式を完全 に理解したいと思います。

元のリファレンスを読んで、Host *+*パターンを使用して、コマンドの再帰呼び出しをよく理解することができました。しかし、2 つの質問があります。

  1. 式は を使用し%%ます。理由を確認するために を使用ssh -vしたところ、sshクライアントが を解析する$HOME/.ssh/configと、最初の%が取り除かれているように見えることがわかりました。上記を確認しようとして、openssh のソース コードをダウンロードしましたがreadconf.c、手がかりが得られませんでした。私は OpenSSH ソース コードを初めて使用しますが、デバッグ情報を使用してコンパイルすることを恐れませんgdb。それにもかかわらず、私の推測を確認するためのより迅速な方法があれば、ヒントをいただければ幸いです。
  2. また、次のssh -vことも明らかにしました。

    [...]
    debug1: Executing proxy command: exec ssh $(echo zackp%node0+zackp%node1+node3 | sed 's/+[^+]*$//;s/\\([^+%]*\\)%\\([^+]*\\)$/\\2 -l \\1/;s/:/ -p /')
    [....]
    

    つまり、サブシェル\(で a を使用してエスケープされるようになりました。\なぜこれが必要なのですか?

ありがとう、

――ザック

4

1 に答える 1

2

良い質問。それはかなり曲がりくねったコマンドです!それはあなたがかなりそれを手に入れたように聞こえます。お使いのマシンでは、ホスト文字列からプラス記号で区切られたホップの 1 つが取り除かれています。便宜上、そのトークンにはポートとユーザーが抽出され、オプション (-lおよび-p) に変換されます。最後に、他のホップに関する情報が文字列にポップされ、netcat に渡されます。マシン上の ssh は 1 つの接続を確立し、残りのホップに関する情報を含む文字列を使用して、ターゲット マシン上で netcat を実行します。その後、同じプロセスがそこで再び発生し、すべてのホップが完了するまで、トラフィックを転送するために各リレーで netcat インスタンスが実行されます。コマンドラインの楽しみのかなり整頓されたビット!

具体的な質問:

  1. % 記号がエスケープされるのはなぜですか? これはProxyCommandオプション固有のものです。に関するmanページからProxyCommand

    コマンド文字列では、'%h' は接続するホスト名に、'%p' はポートに、'%r' はリモート ユーザー名に置き換えられます。

    すべての行儀の良い UNIX ユーティリティと同様に、メタ文字が使用されている場合、自然なことは、その文字を 2 倍にしてリテラルを表すことです。そうしないと、特定の文字列を表す方法がありません! 誰かが % を使ってジャンプリスト用の独自のミニ構文を書き、それを Gentoo wiki に投稿するとは考えずに、単にプログラマーによってきちんとしたものとして追加されたのでしょう!

    % コードはこのオプションに固有のものであるため、エスケープはおそらく OpenSSH ソースでオプションが処理される場所の近くに埋もれています。

  2. くだらない質問!ProxyCommand オプションとして指定された文字列は、ssh に直接渡されるコマンド文字列ではありません。具体的には「ユーザーのシェルを使用して」実行されます。したがって、オプションに含まれるものはユーザーフレンドリーであるため、シェルに入力するものを ssh.conf に入力できます。

    現在、ほとんどの人 (私を含む!) は 100% 正確なログ記録にあまりこだわっていませんが、OpenBSD の連中は、OpenSSH がすべてのログ文字列を出力する前に渡す strnvis 関数を持っています。制御文字やその他の厄介なものをエンコードして、ログ出力が文字列ロギング関数によって渡された正確な (null のない) バッファーの読み取り可能な記録を提供するようにします。これは素晴らしいことですが、唯一の秘訣は、ログを読み取るときに、ログを元の形式に「strunvis」する必要があることです。

    基本的に、バックスラッシュはログ形式の奇妙さです。シェルには渡されません。

    さて、私はここで推測しています (あまり深く掘り下げる価値はないと思います!) が、基本的には、ログ ssh の出力が冗長なときに吐き出されるという質問です。以前にプロセス起動のログを書いたことがありますが、引数が複雑になる可能性があることを考えると、少しずさんな芸術です (改行の埋め込み? 末尾の空白文字? 狂った引用符?)。100%「正確な」方法で exec への引数を無損失でログに記録する必要はありません。面倒すぎるからです。ここにある OpenSSH コードの作成者は、ログに記録する単一の文字列を探しているときに、sh の最後の引数として渡すのに便利だった文字列のエスケープ形式を吐き出したようです。これは、実行される内容の「完全な」表現ではありません (ロギングで空白が失われると思われるため)。

于 2012-08-25T23:54:07.487 に答える