Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I start a program and write its output to a log file, where the log file contains the PID in its name? I tried

program_a > log_$! 

which doesn't work since $! is the PID of the last program and `program_a' has not finished when the log file is created.

share|improve this question
    
Is the program a shell script? –  devnull Mar 19 at 9:23
    
@devnull Nope its not –  greole Mar 19 at 9:26
add comment

4 Answers

You can't do that from the shell that way because the commandline is created before the program is even called. You have essentially two options:

1) Create the filename and write to it from within the program (easy if it is a shell script)

2) Create a named pipe, background the process and then redirect the pipe to a file. Like

mkfifo "tmp.log"  
program_a > "tmp.log" &
cat "tmp.log" > "log_$!"
share|improve this answer
    
Yes, you can. –  Gilles Mar 19 at 22:33
add comment

If you are talking about a script I think this is what you are after...

#!/bin/bash

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

ps

which gave this output

$ 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

Hope that helps.

share|improve this answer
add comment

This doesn't answer the question directly, but I would question why I need to have a file with the pid in the name. If it is simply a unique filename that you are looking for, then there are more robust ways to do this. Most Unices have a mktemp command (unfortunately this is not POSIX though). Using GNU mktemp, you could do:

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

If you have to access the files at a later date, then it may be useful to include the date/time in the filename:

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

If you are looking to ensure that only one instance of a specific process is running, then on Linux you can use flock:

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

Otherwise, if you are looking to have another program read the output of program_a while it is still running, then using a file is surely a method of last resort. Much better to use a pipe or a named pipe as per orion's answer.

share|improve this answer
add comment

You can't know the PID until the process has started. So you need to first start the process, then create the log file, then execute the program you want to execute (exec replaces the calling shell with the given program, it doesn't fork a new process).

sh -c 'exec program_a >log_$$'

$! is the PID of the last program started in the background and cannot help you here.

Alternatively, you could create the log file under a temporary name, start the program, and then rename the log file, but it's needlessly more complicated.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.