Reputation: 23
I have this line of code:
{ time cp $PWD/my_file $PWD/new_file ; } 2> my_log.log
I need to know how long it takes to execute the 'cp' command and I also need to get the PID of the 'cp'. I just want to print the PID of the 'cp' process and get the following in the my_log.log
file:
<output of time>
I have tried PID=$!
but this does not provide PID of the cp
process.
Upvotes: 2
Views: 724
Reputation: 437052
First, you need to send your (timed) cp
command to the background with a trailing &
, so you can inspect the running processes after launching it.
(I suspect you're already doing this, but it's not currently reflected in the question).
$!
, the special variable that contains the PID of the most recently launched background job, in this case reflects the subshell that runs the time
command, so we know that it is the parent process of the cp
command. To get the (one and only, in this case) child process:
If your platform has the nonstandard pgrep
utility (comes with many Linux distros and BSD/macOS platforms), use:
pgrep -P $!
Otherwise, use the following POSIX-compliant approach:
ps -o pid=,ppid= | awk -v ppid=$! '$2 == ppid { print $1 }'
To put it all together, using prgep
for convenience:
# Send the timed `cp` command to the background with a trailing `&`
{ time cp "$PWD/my_file" "$PWD/new_file"; } 2> my_log.log &
# Get the `cp` comand's PID via its parent PID, $!
cpPid=$(pgrep -P $!)
Upvotes: 3
Reputation: 19305
To know approximately how long takes cp command you can check new file size
size=$(stat -c %s "${old_file}")
cp "${old_file}" "${new_file}" &
cp_pid=$!
while kill -0 ${cp_pid}; do
cpsize=$(stat -c %s "${new_file}")
echo elapsed time $(ps -p${cp_pid} -oetime=)
echo $((100*cpsize/size)) % done so far..
sleep 3
done
EDIT: following comment stat -c %s "${file}"
can be replaced by du "${file}"
it's POSIX and more suitable command (see man page).
Upvotes: 2
Reputation: 2003
Following what written in one of your comment above... the following is a proper answer:
The following code (just an example):
time (sleep 10 & echo -n "$!"; wait)
will return something like:
30406
real 0m10.009s
user 0m0.004s
sys 0m0.005s
In your case:
time (cp $PWD/old_file $PWD/new_file & echo -n "$!"; wait) &> my_log.log
will do the job.
I find this solution quite elegant since it's a "one liner" despite the "completely negligible overhead" you got in the timing (the timing will be related to the entire subshell (also the echo
and the wait
). That the overhead is negligible is evident from the result of the sleep command.
The &>
redirect stdout and stderr to the same file (so you do not need to specify the 1>&2
).
Pay attention that doing
(time sleep 10 & echo -n "$!")
You will get the pid of the time
process not sleep
or cp
in your case.
Upvotes: 0
Reputation: 6158
OK -- from the comments: "Contents of my_log.log will be PID of the cp command followed by the timing output of the cp command":
( time cp $PWD/my_file $PWD/new_file & 2>&1; echo $! ) > my_log.log 2>&1
First, you need to use /usr/bin/time
explicitly, and pass the options to append to an output file. Then, use pgrep
on the name of the file you are copying (cp
will get too many hits):
/usr/bin/time --output=my_log.log --append cp $PWD/my_file $PWD/new_file & pgrep -f my_file > my_log.log
You may want to change the output format, because it's kinda ugly:
18400
0.00user 0.30system 0:02.43elapsed 12%CPU (0avgtext+0avgdata 2520maxresident)k
0inputs+496424outputs (0major+141minor)pagefaults 0swaps
Upvotes: 0