web-dev-qa-db-ja.com

コマンドを任意の端末にパイプするにはどうすればよいですか?

私はしばしば一度に複数の端末(または端末エミュレーター)を使用します。 Xでは、コマンドをコピーして貼り付けることができますが、あまり実用的ではないことに加えて、実際のTTYでは明らかに機能しません。私が思いついた最初のアイデアは似たようなものです。

command > /dev/sometty

残念ながら、commandは実行されますbeforeパイプされ、echo `command`のようなトリックは、奇妙なbash文字がいくつあっても機能しません($`"など)があります。したがって、/dev/somettyは単にテキストを取得します。

問題は、これらのコマンドをファイルにパイプしたり、実行可能にしたりするだけの価値がある場合もあります。つまり、スクリプトを作成して適切な端末から実行することです。しかし、それは大変な作業です。指示のために、これらのファイルを作成するためのスクリプトを作成することを考えていました。

termpipe -e "command1\ncommand2\"command 1 argument\\n(s)\"" -t /dev/sometty 

それは次のようなことをします:

  1. コマンドを、たとえば/tmp/termpipe-20140208-153029-1.shにパイプします
  2. ファイルを実行可能にする
  3. 適切な端末でファイルを実行します
  4. 実行が完了したらスクリプトを削除します

AFAIK、問題はにあります:適切な端末で最初のインスタンスを実行するには別のtermpipeインスタンスが必要なので、これは問題を解決しません。そしてそのための1つ。そしてそのためのもう一つ、ad infinitumこれは機能しません。またはそれはできますか?...

解決策は、ターミナルごとに名前付きパイプを使用することであり、各開始時に、スクリプトはパイプに受信したものをターミナルに転送し、それを実行するように指示します(一種のデーモン)。

これはうまくいくかもしれないと思いますが、最初のスクリプトを設定する方法がわかりません。どうやって? FIFOそれぞれの端末を実行するためのパイプコマンドを与えるように指示するにはどうすればよいですか? Bashについてあまり知らないので、完全な説明をいただければ幸いです。

4
JMCF125

this に続いて、あなたの最後の計画をうまく機能させることができます。送信されるコマンドがシェルによって処理されないようにするには、パイプに到達したときに文字列の形式である必要があります(したがって、echo "command"ではなくecho `command`)。次に、適切な端末で開始されたバックグラウンドプロセス( alike adaemon、ただし必ずしもそうではありません)によって読み取られる必要があります。 eval 同じプロセスで使用する必要があります。

ただし、パイプごとにスクリプトを作成するのはboiler-plateyです。それでは、スクリプトの作成をterm-pipe-r.shとして一般化しましょう(chmod +xすることを忘れないでください!):

#!/bin/bash

pipe=$1                     # the pipe name is the first argument
trap 'rm -f "$pipe"' EXIT     # ignore exit and delete messages until the end

if [[ ! -p $pipe ]]; then   # if the pipe doesn't exist, create it
    mkfifo $pipe
fi

while true                  # cycle eternally..
do
    if read line <$ pipe; then
        if [[ "$line" == 'close the term-pipe pipe' ]]; then
            break
            # if the pipe closing message is received, break the while cycle
        fi

        echo                # a line break should be used because of the Prompt 
        eval $line          # run the line: as this script should be started
    fi                          # in the target terminal, 
done                            # the line will be run there.

echo "<pipe closing message>"   # custom message on the end of the script

つまり、/dev/tty3にコマンドを受信させたいとしましょう。

./term-pipe-r.sh tty3pipe &     # $1 will be tty3pipe (in a new process)

そして、コマンドを送信するには、任意の端末から(それ自体からでも):

echo "command" > tty3pipe

またはそこでファイルを実行するには:

cat some-script.sh > tty3pipe

このパイピングは、.bashrcのようなファイルと、そこにあるalias ls='ls --color'のようなエイリアスを無視することに注意してください。これが誰かを助けてくれることを願っています。

編集(注-非デーモンの利点):

上記では、パイプリーダーが必ずしもデーモンではないことについて説明しましたが、実際には、 differences を確認しましたが、この場合、単なるバックグラウンドプロセスになります。このように、ターミナルを閉じると、EXIT信号(SIGHUPSIGTERMなど)もスクリプトによって受信され、パイプが削除されるためです。 (スクリプトのtrapで始まる行を参照)自動的に、無駄なプロセスとファイル(および無駄なパイプへのリダイレクトがあった場合は他のファイル)を回避します。

編集(自動化):

それでも、(少なくとも私は)おそらくほとんどの場合必要なスクリプトを実行しなければならないのは退屈です。それでは、自動化しましょう!どの端末でも start である必要があり、それらすべてが読み取るものの1つは.bashrcです。さらに、./term-pipe-r.shを使用する必要があるのは残念です。だから、人はするかもしれません:

cd /bin # go to /bin, where Bash gets command names
ln -s /directory/of/term-pipe-r.sh tpr  # call it tpr (terminal pipe reader)

これを実行するには、いつでもtpr tty3pipe &/dev/tty3があれば十分です。しかし、それを自動的に実行できるのに、なぜそれを行うのでしょうか。したがって、これを.bashrcに追加する必要があります。しかし待ってください:パイプ名をどうやって知るのでしょうか? tty(および some )の simple REGEXを使用して、TTY(sedコマンドで知ることができます)に基づいて名前を付けることができます。 = トリック )。 ~/.bashrcに追加する必要があるのは次のとおりです。

pipe="$(sed 's/\/dev\///' <<< `tty` | sed 's/\///')pipe"
                # ^^^- take out '/dev/' and other '/', add 'pipe'
tpr $pipe &     # start our script with the appropriate pipe name
5
JMCF125

Vimの変種。 Vimをデフォルトのエディターにする必要があります。

  1. 上/下矢印を使用して、履歴から長いコマンドを選択します。私はこれを選択しました:echo "one two three" > new_file.txt
  2. Ctrl + xCtrl + eの組み合わせを押します。 Vim内で長いコマンドが開きます。 Ctrl + gを押して、vimウィンドウの下部に一時ファイル名を表示します。私の場合は/tmp/bash-fc.230BC2です
  3. 別のttyに移動し、vim /tmp/bash-fc.230BC2と入力します(もちろん、ファイル名のオートコンプリートを使用します)。 「スワップファイルはすでに存在します」と表示されます。読み取り専用の場合は、Oを押します。
  4. 次に、vim内で、次のキーシーケンスが必要です:y$ : ! Ctrl+r " Enter
    説明
    • y$-末尾の改行を除く行のすべての文字をコピーします。
    • :-コマンドラインモードに移動します
    • !-シェルでコマンドを実行する
    • Ctrl+r "-コピーした行をコマンドラインに貼り付けます。
    • Enter-コマンドを実行します

.vimrcファイル編集により、このすべてのキーシーケンスを1つのキーストロークにマッピングできることに注意してください。

コマンドが1つのttyから別のttyにコピーされ、実行されました。

0
MiniMax