linux - bash如何在后台保存multiply进程的返回值?

标签 linux bash

我试图在后台保存每个并行运行并在不同时间结束的进程的返回值。

例如(这里的返回值在所有进程中都是0,但在我的脚本中会有很多返回值):

    #!/bin/bash
    echo "" > empty.txt
    (sleep 4 ; echo "my return value is $? " >> empty.txt ) &
    (sleep 3 ; echo "my return value is $? " >> empty.txt ) &
    (sleep 12 ; echo "my return value is $? " >> empty.txt ) &
    (sleep 9 ; echo "my return value is $? " >> empty.txt ) &
    (sleep 7 ; echo "my return value is $? " >> empty.txt ) &
    (sleep 6 ; echo "my return value is $? " >> empty.txt ) &
    (sleep 4 ; echo "my return value is $? " >> empty.txt ) &

但是这里我不知道每个进程的返回值是多少(我只是把它们都放在一个文件中)

我可以使用 mkfifo 来解决这个问题吗?每个进程在进入fifo时都会有一个编号,并且他的返回值会按照先进先出的顺序绑定(bind)。

我试过这样的:

#!/bin/bash
mkfifo pipe1
(sleep 4 ; echo "my return value is $? " >> $pipe1 ) &
(sleep 6 ; echo "my return value is $? " >> $pipe1 ) &
(sleep 9 ; echo "my return value is $? " >> $pipe1 ) &
(sleep 2 ; echo "my return value is $? " >> $pipe1 ) &
(sleep 12 ; echo "my return value is $? " >> $pipe1 ) &
(sleep 4 ; echo "my return value is $? " >> $pipe1 ) &

但它不起作用。也许我没有使用 fifo,对吗?

最佳答案

只要您的输出足够短以适合单个写入调用(以避免交错):

for ((x=0; x<10; x++)); do
  (sleep $((RANDOM % 10)); echo "My number is $x and my return value is $?") &
done >output.txt

如果这不够安全,您可以锁定:

for ((x=0; x<10; x++)); do
  (sleep $((RANDOM % 10))
   retval=$?
   exec {lock_fd}>.output_lock                        # open the lockfile
   flock -x "$lock_fd"                                # grab the lock
   echo "My number is $x; my return value is $retval" # do the write
  ) &                                                 # lock released by subshell exit
done >output.txt

...替换 .output_lock带有要用于协调的锁定文件的文件名。


请注意 {lock_fd}>.output_lock是需要 bash 4.1 或更新版本的语法;对于较旧的 shell,您需要自己分配一个 FD 编号——例如,3>.output_lock -- 并在调用 flock 时使用该号码稍后。


您还可以通过调用 wait 来避免整个锁定问题。依次在每个子进程(及其 PID)上从父进程收集它们的退出状态值。

即:

#!/bin/bash

declare -a pids=( )
for ((x=0; x<10; x++)); do
  sleep $((RANDOM % 10)) &
  pids[$x]=$!
done

for pid in "${!pids[@]}"; do
  wait "$pid"
  echo "Child with PID $pid exited with status $?"
done >output.txt

这样做的缺点是您不会在作业退出时立即获得输出——相反,即使作业以不同的顺序退出,反馈也会按进程 ID 的顺序给出。


当然,另一种方法是将每个作业的退出状态写入不同的文件。

for ((x=0; x<10; x++)); do
  (sleep $((RANDOM % 10)); echo "My number is $x and my return value is $?" >"output.$x.txt") &
done

关于linux - bash如何在后台保存multiply进程的返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29221925/

相关文章:

c - mmap 导致堆栈损坏,涉及内核吗?

linux - 如何使用 sed/awk/grep

bash - 使用 shUnit2 在 bash 脚本中测试 "exit process command"

linux - 如何运行脚本取决于不同的停止时间

bash - 在 bash 的左侧为多部分命令别名

linux - 无法在 Arch Linux 上安装 libc++

linux - Linux 套接字编程的最佳实践

linux - 在 Linux 上构建可嵌入(最小)Python 发行版

bash - 设置动态创建的 bash 变量

git - 为什么 .gitignore 不忽略 .DS_Store?