1. ホーム
  2. linux

[解決済み] 既に実行中のプロセスの出力をリダイレクトする方法 [重複]。

2022-04-29 01:34:52

質問

通常であれば、次のようなコマンドを起動します。

longcommand &;

のようにすれば、リダイレクトできるのは知っています。

longcommand > /dev/null;

を出力させないようにしたり

longcommand 2>&1 > output.log

で出力をキャプチャします。

しかし、私は時々忘れてしまうので、事後的にキャプチャまたはリダイレクトする方法はないかと考えていました。

longcommand
ctrl-z
bg 2>&1 > /dev/null

などと書いておくと、ターミナルにメッセージが出ずに使い続けられます。

解決方法は?

参照 実行中のプロセスからの出力をリダイレクトする .

まず最初にコマンドを実行します。 cat > foo1 をあるセッションで実行し、stdinからのデータがファイルにコピーされることをテストします。次に、別のセッションで出力をリダイレクトします。

まず、プロセスのPIDを探します。

$ ps aux | grep cat
rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat

次に、開いているファイルハンドルを確認します。

$ ls -l /proc/6760/fd
total 3
lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1
lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5

ここでGDBを実行します。

$ gdb -p 6760 /bin/cat
GNU gdb 6.4.90-debian

[license stuff snipped]

Attaching to program: /bin/cat, process 6760

[snip other stuff that's not interesting now]

(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/foo3", 0600)
$2 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760

p GDB のコマンドは式の値を表示します。式は呼び出す関数であったり、システムコールであったりします...そこで、私は close() システムコールを実行し、ファイルハンドル1を渡し、次に creat() システムコールを使って新しいファイルを開きます。その結果 creat() は1であり、これは前のファイルハンドルを置き換えたことを意味します。もし標準出力と標準エラーに同じファイルを使いたい場合、あるいはファイルハンドルを他の番号に置き換えたい場合、私は dup2() システムコールで実現します。

この例では creat() の代わりに open() というのは、パラメータが少ないからです。フラグのCマクロはGDBからは使えないので(Cヘッダを使わない)、これを発見するためにはヘッダファイルを読む必要があります。0600は、所有者が読み取り/書き込みのアクセス権を持ち、グループとその他がアクセス権を持たないことを示す8進数のパーミッションであることに注意してください。このパラメータに0を指定して、後でそのファイルに対してchmodを実行することも可能です。

その後、結果を検証しています。

ls -l /proc/6760/fd/
total 3
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <====
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5

にさらにデータを打ち込む。 cat の結果は、ファイル /tmp/foo3 に追加される。

元のセッションを閉じたい場合は、そのセッションのファイルハンドルをすべて閉じ、制御用ttyとなりうる新しいデバイスを開いてから setsid() .