0

コマンドラインの存在を簡素化するために書いた多くの bash/bind ツールがあり、最近、これらのツールの 1 つをインタラクティブにしたいと考えています。これらのスクリプトのいずれかで stdin から読み取ろうとすると、読み取りの時点で実行がロックされます。ここでの私の例は python ですが、呼び出されたスクリプトが ruby​​ で書かれている場合、まったく同じ動作を見てきました。

~> cat tmp.py
import sys
sys.stdout.write(">>>")
sys.stdout.flush()
foo = sys.stdin.readline()
print "foo: %s" % foo,


~> python tmp.py
>>>yodeling yoda
foo: yodeling yoda

したがって、スクリプトは機能します。それを呼び出すと、入力を与えることができ、フィードしたものが出力されます。

~> bind -x '"\eh":"echo yodeling yoda"'
[output deleted]

~> [Alt-H]
yodeling yoda

bind期待どおりに動作します。バインドされたキーストロークがコマンドを呼び出します。私はいつもこのようなものを使用していますが、今までは、stdin 読み取りを必要としないスクリプトしか呼び出していませんでした。

[Alt-H] をスクリプトにバインドしましょう:

~> bind -x '"\eh":"python tmp.py"'
[output deleted]

これで、バインドされたキーストロークによって呼び出されたときにスクリプトが stdin から読み取られるように構成されました。[Alt-H] を押すとスクリプトが開始されますが、何も入力されていません。[Crl-D]を押しても終わらない。抜け出す唯一の方法は、[Crl-C] を押して readline のプロセスを強制終了することです。(sys.stdin.read() も同じ運命をたどります。)

~> [Alt-H]
>>>Traceback (most recent call last):
  File "tmp.py", line 7, in <module>
    foo = sys.stdin.readline()
KeyboardInterrupt

冒頭で述べたように、Ruby でも同じ問題が見られるので、使用している言語とは関係ないことはわかっています。(スクリプトは省略しました。)

~> bind -x '"\eh":"ruby tmp.rb"'
[Output deleted]

~> [Alt-H]
>>>tmp.rb:3:in `gets': Interrupt
    from tmp.rb:3

バインドに関する Bash リファレンス マニュアルのエントリに目を通しましたが、入力の制限については何も述べていません。何かご意見は?

編集:

プロセスがスタックしている間に /proc/[PID]/fd/0 を cat すると、スクリプトの入力が表示されます。(奇妙なことに、ランダムに見えるかなりの数の文字がここに表示されません。この症状は、数百バイトの入力を行った後にのみ表示されます。)

thisを見つけました。これは、端末がクック モードと生モードを切り替える方法とタイミングの説明です。プロンプトの開始時に呼び出しstty cooked、その後またはその後に呼び出しを行うと、問題の新しいカスケードがトリガーされます。主にバインドされた文字の処理方法に関連していますが、return が数回ヒットするまで、ほとんどの alt バインディング (およびそれ以上) を破壊すると言えば十分です。stty echostty sanestty raw

4

2 に答える 2

0

うーん、私の推測では、[Alt-H] を押したときに python スクリプトが実行され、stdin からの入力を待っていますが、stdin スコープは呼び出しスクリプトの stdin スコープと同じではありません。何かを入力すると、Python ではなく Bash スクリプトの stdin に送られます。おそらく、「逆パイプ」または標準入力を bash シェルから呼び出されたスクリプトの標準入力に転送する方法を調べてください。

編集:

わかりました、少し調べてみましたが、パイプが機能するようです。ここに非常に有益なリンクがあります: bash - 特定の出力を 2 番目のスクリプトから最初のプログラムの標準入力にリダイレクトしますか?

于 2013-06-04T22:55:29.370 に答える