シェルスクリプト内で、STDOUTおよびSTDERRがリダイレクトされている間に画面に書き込むことはできますか?
STDOUTとSTDERRをキャプチャするシェルスクリプトがあります。スクリプトはおそらく1時間以上実行されるので、表示され、リダイレクトされない(キャプチャされない)画面にステータスメッセージをときどき書き込みます。
最小限の例として、シェルスクリプトがあります。「./ myscript.sh」としましょう。
#!/bin/sh -u
echo "Message A: This writes to STDOUT or wherever '1>' redirects to."
echo "Message B: This writes to STDOUT or wherever '1>' redirects to.">&1
echo "Message C: This writes to STDERR or wherever '2>' redirects to.">/dev/stderr
echo "Message D: This writes to STDERR or wherever '2>' redirects to.">&2
echo "Message E: Write this to 'screen' regardless of (overriding) redirection." #>???
たとえば、次のようなスクリプトを実行すると、この出力が表示されます。
[~]# ./myscript.sh > fileout 2> filerr
Message E: Write this to 'screen' regardless of (overriding) redirection.
[~]# ./myscript.sh > /dev/null 2>&1
Message E: Write this to 'screen' regardless of (overriding) redirection.
[~]#
これを「直接」実行できない場合、一時的にリダイレクトを中止し、画面に何かを印刷して、リダイレクトを以前の状態に戻すことはできますか?
コンピューターに関するいくつかの情報:
[~]# uname -srvmpio
Linux 3.2.45 #4 SMP Wed May 15 19:43:53 CDT 2013 x86_64 x86_64 x86_64 GNU/Linux
[~]# ls -l /bin/sh /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 4 Jul 18 23:18 /bin/sh -> bash
lrwxrwxrwx 1 root root 15 Jun 29 2013 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jun 29 2013 /dev/stdout -> /proc/self/fd/1
次のようなスクリプトを試してください。
#!/bin/bash
echo "to fd1" >&1
echo "to fd2" >&2
echo "to screen" >$(tty)
呼び出すと、次のようになります。
user@Host:~# ./script
to fd1
to fd2
to screen
user@Host:~# ./script 1>/dev/null
to fd2
to screen
user@Host:~# ./script 2>/dev/null
to fd1
to screen
user@Host:~# ./script > /dev/null 2>&1
to screen
私はすべてのttyリダイレクションについて知りませんが、これは私がすることです:
実際にはリダイレクトせず、必要な出力をパラメーターとして送信するか、スクリプト自体でリダイレクトする場合は、次のコマンドを実行することでいつでもリダイレクトを切り替えることができます。
exec 2> /some/new/destination 1> /some/other/destination
古いものを保存したいかもしれません...
exec 3>&1 4>&2 2> /some/new/destination 1> /some/other/destination
そうすれば、それに戻ることができます...完了したとき、または画面に書き込みたいとき
画面に書き込む:echo "message" 1>&3
または..
すべて完了: exec 1>&3 2>&4
#すべてが正常に戻ります:)
chaosによる回答の例を使用します。
echo "to screen" >$(tty)
私にとってはうまくいきませんでした。使用しようとするとエラーが発生します。
./myscript.sh: line xx: /dev/pts/3: Permission denied
別のファイル記述子を使用するための解決策を思いつきました(9)。これが「./myscript.sh」です。
#!/bin/sh -u
## This is placed one time at the top of the script
## to detect if file descriptor (9) is available for writing.
if [ ! -t 3 ]; then
echo "Error, file descriptor (9) not open on terminal." >&2
echo "" >&2
if [ ! -t 2 ]; then
echo "Error, file descriptor (9) not open on terminal."
echo ""
fi
exit 1
fi
echo "Message A: This writes to stdout or wherever '1>' redirects to."
echo "Message B: This writes to stdout or wherever '1>' redirects to.">&1
echo "Message C: This writes to stderr or wherever '2>' redirects to.">/dev/stderr
echo "Message D: This writes to stderr or wherever '2>' redirects to.">&2
echo "Message E: Write this to 'screen' regardless of '1>/2>' redirection." >&9
echo " " >&9
私はファイル記述子を使用しました9
「ステータス」メッセージを出力しますが、他の有効なファイル記述子が機能するはずです。
これを使用するには、スクリプトを呼び出すときに、最初のリダイレクトとしてファイル記述子(9)のSTDOUT(9>&1)へのリダイレクトを含める必要があります。
「./myscript.sh」を呼び出したときの出力は次のとおりです。
[~]# ./myscript.sh
[~]# ./myscript.sh >/dev/null
[~]# ./myscript.sh 2>/dev/null
Error, file descriptor (9) not open on terminal.
[~]# ./myscript.sh >/dev/null 9>&1
Error, file descriptor (9) not open on terminal.
[~]# ./myscript.sh 9>&1 >/dev/null
Message C: This writes to stderr or wherever '2>' redirects to.
Message D: This writes to stderr or wherever '2>' redirects to.
Message E: Write this to 'screen' regardless of '1>/2>' redirection.
[~]# ./myscript.sh 9>&1 2>/dev/null
Message A: This writes to stdout or wherever '1>' redirects to.
Message B: This writes to stdout or wherever '1>' redirects to.
Message E: Write this to 'screen' regardless of '1>/2>' redirection.
[~]# ./myscript.sh 9>&1 >/dev/null 2>&1
[~]# ./myscript.sh 9>&1 &>/dev/null
[~]# ./myscript.sh 9>&1 >&/dev/null
Message E: Write this to 'screen' regardless of '1>/2>' redirection.
[~]#