web-dev-qa-db-ja.com

名前にPIDを含むログファイルにプログラム出力を書き込む

プログラムを起動して、その出力をログファイルに書き込むにはどうすればよいですか。ログフ​​ァイルの名前にはPIDが含まれています。私は試した

program_a > log_$! 

$以降は機能しません!は最後のプログラムのPIDであり、ログファイルの作成時に `program_a 'は終了していません。

2
greole

あなたがスクリプトについて話しているなら、私はこれがあなたが求めているものだと思います...

#!/bin/bash

exec 1>test_$$.txt 
echo "Hello \$\$ == $$" 

ps

この出力を与えた

$ cat test_20000.txt 
Hello $$ == 20000
  PID TTY           TIME CMD
18651 ttys000    0:00.06 -bash
20000 ttys000    0:00.00 /bin/bash ./execredir.sh
2
Vic

プログラムが呼び出される前にコマンドラインが作成されるため、シェルからそのように行うことはできません。基本的に2つのオプションがあります。

1)ファイル名を作成し、プログラム内から書き込みます(シェルスクリプトの場合は簡単です)

2)名前付きパイプを作成し、プロセスをバックグラウンドで実行してから、パイプをファイルにリダイレクトします。お気に入り

mkfifo "tmp.log"  
program_a > "tmp.log" &
cat "tmp.log" > "log_$!"
1
orion

これは質問に直接答えることはありませんが、名前にpidが含まれるファイルが必要な理由については疑問があります。探しているのが単に一意のファイル名である場合は、これを行うためのより堅牢な方法があります。ほとんどのユニスにはmktempコマンドがあります(残念ながら、これはPOSIXではありません)。 GNU mktempを使用すると、次のことができます。

tmp_file=$(mktemp --tmpdir=. log_XXXXXXXXXX)
program_a >"$tmp_file"

後日ファイルにアクセスする必要がある場合は、ファイル名に日付/時刻を含めると便利な場合があります。

log_file=$(mktemp --tmpdir=. log_"$(date +%F_%T)".XXX)
program_a >"$log_file"

特定のプロセスのインスタンスが1つだけ実行されていることを確認したい場合は、Linuxでflockを使用できます。

(
  flock -n 9 || { echo "program_a already running"; exit 1; }
  program_a
) 9>/var/lock/program_a

それ以外の場合、実行中に別のプログラムにprogram_aの出力を読み取らせたい場合は、ファイルを使用することが確実に最後の手段です。 orionの答え に従って、パイプまたは名前付きパイプを使用する方がはるかに優れています。

1
Graeme

プロセスが開始されるまで、PIDを知ることはできません。したがって、最初にプロセスを開始し、次にログファイルを作成してから、実行するプログラムを実行する必要があります(execは、呼び出し元のシェルを指定されたプログラムに置き換えます。新しいプロセスをフォークしません)。

sh -c 'exec program_a >log_$$'

$!は、バックグラウンドで開始された最後のプログラムのPIDであり、ここでは役に立ちません。

または、一時的な名前でログファイルを作成し、プログラムを起動してから、ログファイルの名前を変更することもできますが、それは不必要に複雑です。