获取定时进程的 PID,以及时间的输出
Get PID of a timed process, along with the output of time
我有这行代码:
{ time cp $PWD/my_file $PWD/new_file ; } 2> my_log.log
我需要知道执行 'cp' 命令需要多长时间,我还需要获取 'cp' 的 PID。我只想打印 'cp' 进程的 PID 并在 my_log.log
文件中获取以下内容:
<output of time>
我试过 PID=$!
但这不提供 cp
进程的 PID。
我能想到的最简单的就是
pgrep cp
好的——来自评论:"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
首先,您需要明确地使用 /usr/bin/time
,并传递选项以附加到输出文件。然后,在您要复制的文件的名称上使用 pgrep
(cp
会获得太多点击):
/usr/bin/time --output=my_log.log --append cp $PWD/my_file $PWD/new_file & pgrep -f my_file > my_log.log
您可能想要更改输出格式,因为它有点难看:
18400
0.00user 0.30system 0:02.43elapsed 12%CPU (0avgtext+0avgdata 2520maxresident)k
0inputs+496424outputs (0major+141minor)pagefaults 0swaps
根据您在上面的评论中写的内容...以下是正确的答案:
下面的代码(只是一个例子):
time (sleep 10 & echo -n "$!"; wait)
会 return 像这样:
30406
real 0m10.009s
user 0m0.004s
sys 0m0.005s
你的情况:
time (cp $PWD/old_file $PWD/new_file & echo -n "$!"; wait) &> my_log.log
会完成任务的。
我发现这个解决方案非常优雅,因为它是一个 "one liner",尽管你在时间上得到了 "completely negligible overhead"(时间将与整个子外壳相关(还有 echo
和wait
)。从睡眠命令的结果可以明显看出开销可以忽略不计。
&>
将 stdout 和 stderr 重定向到同一个文件(因此您不需要指定 1>&2
)。
注意
(time sleep 10 & echo -n "$!")
您将获得 time
进程的 pid,而不是您的 sleep
或 cp
。
要了解 cp 命令大约需要多长时间,您可以检查新文件大小
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
编辑:以下评论 stat -c %s "${file}"
可以替换为 du "${file}"
它是 POSIX 和更合适的命令(参见手册页)。
首先,您需要将您的(定时的)cp
命令发送到后台并带有尾随 &
,这样您就可以在之后检查 运行 进程启动它。
(我怀疑你已经在这样做了,但它目前没有反映在问题中)。
$!
,包含最近启动的后台作业的 PID 的特殊变量,在本例中反映运行 subshell time
命令,所以我们知道是cp
命令的parent进程。要获得(在本例中是唯一的)子进程:
如果您的平台有非标准 pgrep
实用程序(许多 Linux 发行版和 BSD/macOS 平台附带),请使用:
pgrep -P $!
否则,请使用以下符合 POSIX 的方法:
ps -o pid=,ppid= | awk -v ppid=$! ' == ppid { print }'
为了方便起见,使用 prgep
将它们放在一起:
# 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 $!)
我有这行代码:
{ time cp $PWD/my_file $PWD/new_file ; } 2> my_log.log
我需要知道执行 'cp' 命令需要多长时间,我还需要获取 'cp' 的 PID。我只想打印 'cp' 进程的 PID 并在 my_log.log
文件中获取以下内容:
<output of time>
我试过 PID=$!
但这不提供 cp
进程的 PID。
我能想到的最简单的就是
pgrep cp
好的——来自评论:"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
首先,您需要明确地使用 /usr/bin/time
,并传递选项以附加到输出文件。然后,在您要复制的文件的名称上使用 pgrep
(cp
会获得太多点击):
/usr/bin/time --output=my_log.log --append cp $PWD/my_file $PWD/new_file & pgrep -f my_file > my_log.log
您可能想要更改输出格式,因为它有点难看:
18400
0.00user 0.30system 0:02.43elapsed 12%CPU (0avgtext+0avgdata 2520maxresident)k
0inputs+496424outputs (0major+141minor)pagefaults 0swaps
根据您在上面的评论中写的内容...以下是正确的答案:
下面的代码(只是一个例子):
time (sleep 10 & echo -n "$!"; wait)
会 return 像这样:
30406
real 0m10.009s
user 0m0.004s
sys 0m0.005s
你的情况:
time (cp $PWD/old_file $PWD/new_file & echo -n "$!"; wait) &> my_log.log
会完成任务的。
我发现这个解决方案非常优雅,因为它是一个 "one liner",尽管你在时间上得到了 "completely negligible overhead"(时间将与整个子外壳相关(还有 echo
和wait
)。从睡眠命令的结果可以明显看出开销可以忽略不计。
&>
将 stdout 和 stderr 重定向到同一个文件(因此您不需要指定 1>&2
)。
注意
(time sleep 10 & echo -n "$!")
您将获得 time
进程的 pid,而不是您的 sleep
或 cp
。
要了解 cp 命令大约需要多长时间,您可以检查新文件大小
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
编辑:以下评论 stat -c %s "${file}"
可以替换为 du "${file}"
它是 POSIX 和更合适的命令(参见手册页)。
首先,您需要将您的(定时的)
cp
命令发送到后台并带有尾随&
,这样您就可以在之后检查 运行 进程启动它。 (我怀疑你已经在这样做了,但它目前没有反映在问题中)。$!
,包含最近启动的后台作业的 PID 的特殊变量,在本例中反映运行 subshelltime
命令,所以我们知道是cp
命令的parent进程。要获得(在本例中是唯一的)子进程:如果您的平台有非标准
pgrep
实用程序(许多 Linux 发行版和 BSD/macOS 平台附带),请使用:
pgrep -P $!
否则,请使用以下符合 POSIX 的方法:
ps -o pid=,ppid= | awk -v ppid=$! ' == ppid { print }'
为了方便起见,使用 prgep
将它们放在一起:
# 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 $!)