简体   繁体   English

识别shell中触发的并行进程的结束时间戳

[英]identify the end timestamp of the parallel process triggered in shell

process p3 completes first than the other two but the process is waiting till the process p1 is completed and the end_time is the same for all the 3 processes.进程 p3 比其他两个进程先完成,但进程正在等待进程 p1 完成,并且所有 3 个进程的 end_time 都相同。 But i want to get the timestamp of p3 process as soon as it is completed and the same with p2 and p1.但是我想在完成后立即获取 p3 进程的时间戳,并且与 p2 和 p1 相同。 Thanks in advance提前致谢

p1_start_time=`date "+%Y-%m-%d %H:%M:%S"`
sleep 100 &
p1=$!

p2_start_time=`date "+%Y-%m-%d %H:%M:%S"`
sleep 60 &
p2=$!

p3_start_time=`date "+%Y-%m-%d %H:%M:%S"`
sleep 20 &
p3=$!


$(wait $p1 ; rc=$? ; p1_end_time=`date "+%Y-%m-%d %H:%M:%S"`) &
$(wait $p2 ; rc=$? ; p2_end_time=`date "+%Y-%m-%d %H:%M:%S"`) &
$(wait $p3 ; rc=$? ; p3_end_time=`date "+%Y-%m-%d %H:%M:%S"`) &

wait

echo "out of wait"

echo "$p1_end_time"
echo "$p2_end_time"
echo "$p3_end_time"

The 3x backgrounded (aka 'child') pids (p1 / p2 / p3) are available to the main/calling process (aka the 'parent'). 3x 后台(又名“子”)pid(p1 / p2 / p3)可用于主/调用进程(也称为“父”)。 Only the 'parent' process can use the wait command to wait for the 'child' processes to complete.只有“父”进程可以使用wait命令等待“子”进程完成。

For each of the $(wait $p ...) constructs a separate OS-level process is spawned and while you can pass the background pids to these new processes, said processes are not the 'parent' of said background pids;对于每个$(wait $p ...)构造一个单独的操作系统级进程会产生,虽然您可以将后台 pid 传递给这些新进程,但所述进程不是所述后台 pid 的“父”; the net effect is the three wait $p# calls are (effectively) ignored and the 3x p#_end_time variables are immediately populated with the current date/time.最终效果是三个wait $p#调用被(有效地)忽略,3x p#_end_time变量立即填充当前日期/时间。 But, keep in mind the 3x p#_end_time variables are being assigned within separate sub-processes which means when said processes exit the associated p#_end_time variables are discarded (ie, the values are not passed back 'up' to the main/calling process).但是,请记住,3x p#_end_time变量是在单独的子进程中分配的,这意味着当所述进程退出关联的p#_end_time变量时,将丢弃相关的p#_end_time变量(即,这些值不会“向上”传递回主进程/调用过程)。

Also keep in mind that when a process is put in the background it is executed asynchronously, which means a separate OS-level process is spawned.还要记住,当一个进程被置于后台时,它是异步执行的,这意味着会产生一个单独的操作系统级进程。 In order to pass data back 'up' to the main/calling process (eg, in this case the end time of the background processes) it becomes necessary to implement some sort of inter-process communications or use an intermediate storage option for sharing data (eg, pipe, file, database table, queuing system, etc).为了将数据“向上”传递给主进程/调用进程(例如,在这种情况下,后台进程的结束时间)有必要实现某种进程间通信或使用中间存储选项来共享数据(例如,管道、文件、数据库表、排队系统等)。

One idea for capturing the separate end times:捕获单独结束时间的一种想法:

  • upon exiting the sleep , write the current date/time to a temp file;退出sleep ,将当前日期/时间写入临时文件; this is how we'll pass data 'up' from the background (aka child) processes to the parent process这就是我们将数据从后台(又名子)进程“向上”传递到父进程的方式
  • while not an issue for this scenario, we'll have each child process write to a separate temp file to alleviate any issues with race conditions and scrambling of data when multiple processes write to the same file at the same time虽然在这种情况下不是问题,但我们将让每个子进程写入一个单独的临时文件,以在多个进程同时写入同一个文件时缓解竞争条件和数据扰乱的任何问题
  • for this answer I'm going to use a couple arrays to store the start and end times;对于这个答案,我将使用几个数组来存储开始时间和结束时间; this allows for a little less coding by using a couple loops这允许通过使用几个循环来减少编码
  • if the OP needs to use explicit variables for each start/end pair then the loops can be replaced with individual calls using the explicit variable names如果 OP 需要为每个开始/结束对使用显式变量,则可以使用显式变量名称将循环替换为单独的调用

One implementation:一种实现:

unset pstart pend                                 # delete any variables with these names
pstart=()                                         # init arrays for
pend=()                                           # start and end times

outdir=$(mktemp -d)                               # create temp directory for storing temp files containing end date/times

stime=100                                         # initial sleep time

for i in {1..3}                                   # we'll do 3x passes through the loop
do
    pstart["${i}"]=$(date "+%Y-%m-%d %H:%M:%S")   # save the start date/time

    # kick off sleep + 'echo date/time > temp file' in the background; each sub-process will have a different OS-level pid == BASHPID

    (sleep "${stime}"; echo "${i} "$(date "+%Y-%m-%d %H:%M:%S") > "${outdir}/${BASHPID}") &

    stime=$((stime-40))                           # OP's example just happens to use times that are 40 seconds apart
done

wait                                              # wait for all background processes to complete

# load our end times into the pend array

while read -r i dt
do
    pend["${i}"]="${dt}"
done < <(cat "${outdir}"/[0-9]*)

# display start/end times for our processes (OP can reformat as needed)

for i in {1..3}
do
    echo "process #${i} start/end times: ${pstart[${i}]} - ${pend[${i}]}"
done

# get rid of the temp directory and files

'rm' -rf "${outdir}" >/dev/null 2>&1

The output from a sample run:示例运行的输出:

process #1 start/end times: 2020-10-14 22:49:28 - 2020-10-14 22:51:08
process #2 start/end times: 2020-10-14 22:49:28 - 2020-10-14 22:50:28
process #3 start/end times: 2020-10-14 22:49:28 - 2020-10-14 22:49:48

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM