ボリュームを共有する2つのコンテナXとY(実際には同じKubernetesポッドにある2つのコンテナ)があるとします。このボリュームには、/foo
コンテナYのbashプロセスに接続する名前付きパイプがあります。コンテナXがコンテナYにデータを送信するときは、たとえば次のように操作したいと思いますssh
。コマンドはリモートbashシェル、パイプなどから読み取る必要があり、すべて透過的に処理されます。
マシンYで以下を試しました。
bash -s <> /foo
:XIマシンで実行すると、echo “ls -l” > /foo; cat /foo
コマンドはYで実行されますが、出力は名前付きパイプの代わりにYの端末に移動します。bash -s < /foo > /foo
マシンXIで実行してもecho “ls -l” > /foo; cat /foo
何も起こりません。bash -s < /foo | cat - > foo
:XIマシンで実行すると、コマンドがecho “ls -l” > /foo; cat /foo
Yで実行され、出力がXの端末に表示され、次にYでコマンドが実行されず、Xが停止します。
私が探しているのは、Xの現在のシェルを名前付きパイプに接続し、それをXの新しいシェルに接続する方法です。もう一度言うが、以前のように動作したいと思いますssh
。単一の非対話型コマンド(またはスクリプト)および/またはパイプデータを接続して送信でき、何とか期待どおりに機能します。私はそれを実装するのに適したシェルfuを見つけることができませんでした。
また、上記の3つのオプションがなぜ異なる結果を生み出すのか理解していません。
答え1
bashシェルを名前付きパイプに接続するには、このexec
コマンドを使用して、現在のシェルプロセスを名前付きパイプに関連付けられている新しいプロセスに置き換えます。たとえば、マシンYでこれを行う方法は次のとおりです。
cat /foo | bash
これは現在のシェルプロセスを名前付きパイプを読み書きする新しいシェルプロセスに置き換えます/foo
。マシンXから送信されたすべてのコマンドまたはデータは、/foo
マシンYの新しいシェルプロセスから読み取られます。
3回の試みと他の結果について:
bash -s <> /foo
:このコマンドは、標準入力から読み取って標準出力に書き込む新しいシェルプロセスを実行します。この<>
構文は、読み書き用の名前付きパイプを開くようにシェルに指示します。マシンXで実行すると、名前付きecho "ls -l" > /foo
パイプに "ls -l"文字列を書き込んでから、マシンYの新しいシェルプロセスからそれを読み込みます。コマンドはYで実行されますが、Yの端末に印刷された出力は名前付きパイプに書き込まれます。bash -s < /foo > /foo
:このコマンドは、名前付きパイプからデータを読み書きする新しいシェルプロセスを実行します。 X マシンで実行すると、名前付きecho "ls -l" > /foo
パイプに "ls -l" 文字列を記録し、Y マシンの新しいシェル プロセスからそれを読み込みます。ただし、シェルプロセスは同じ名前付きパイプに書き込むため、デッドロックが発生し、何も起こりません。bash -s < /foo | cat - > foo
:このコマンドは、名前付きパイプからデータを読み取り、その出力を通常のファイルに書き込むcatコマンドにパイプする新しいシェルプロセスを実行しますfoo
。マシンXで実行すると、名前付きecho "ls -l" > /foo
パイプに "ls -l"文字列を書き込んでから、マシンYの新しいシェルプロセスからそれを読み込みます。コマンドはYで実行され、出力はXで実行されているcatプロセスに書き込まれるため、Xの端末に表示されます。ただし、catプロセスは名前付きパイプには何も書き換えないため、Yシステムの新しいシェルプロセスは中断されます。
答え2
いいですね。 Telometto、Kamil、Greg A. Woodsの助けを借りて、私は私の要件を満たす次の解決策を思いつきました。
- 共有ボリュームから以下を作成します。サム名前付きパイプ
stdin
とstdout
stderr
- マシンYで実行
while true; do bash -s < stdin 2> stderr > stdout ; done
- リモートコマンドの実行を支援するために、マシンXIにヘルパースクリプトを作成しました。
#!/bin/bash
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM
(
echo "$@"
if read -t 0 ; then
cat - 2> /dev/null
fi
) | cat > stdin
cat stdout &
cat stderr > /dev/stderr &
wait
これを使用するには、./run "ls -l"
Xから始めてYからコマンドを実行します。 Xから始めてYからコマンドを実行して、./run "cat > bar" < foo
Xの内容をYに移動することもできます。foo
パイプ入力も同様に処理されます。