如何从后台进程linux shell脚本获取结果?

如何从后台进程linux shell脚本获取结果?,linux,shell,command-line,Linux,Shell,Command Line,例如,假设我要计算10个大文件的行数,并打印总数 for f in files do #this creates a background process for each file wc -l $f | awk '{print $1}' & done 我试着说: for f in files do #this does not work :/ n=$( expr $(wc -l $f | awk '{print $1}') + $n ) & d

例如,假设我要计算10个大文件的行数,并打印总数

for f in files
do
    #this creates a background process for each file
    wc -l $f | awk '{print $1}' &
done
我试着说:

for f in files
do
    #this does not work :/
    n=$( expr $(wc -l $f | awk '{print $1}') + $n ) &
done

echo $n

我终于找到了一个使用匿名管道和bash的有效解决方案:

#!/bin/bash

# this executes a separate shell and opens a new pipe, where the 
# reading endpoint is fd 3 in our shell and the writing endpoint
# stdout of the other process. Note that you don't need the 
# background operator (&) as exec starts a completely independent process.
exec 3< <(./a.sh 2&1)


# ... do other stuff


# write the contents of the pipe to a variable. If the other process
# hasn't already terminated, cat will block.
output=$(cat <&3)
#/bin/bash
#这将执行一个单独的shell并打开一个新管道,其中
#在我们的shell中,读取端点是fd3,写入端点是fd3
#另一个进程的stdout。请注意,您不需要
#后台操作员(&)作为exec启动一个完全独立的进程。

exec 3<您可以将其写入文件或更好的方式,在数据到达时立即收听fifo

下面是一个关于它们如何工作的小例子:

# create the fifo
mkfifo test

# listen to it
while true; do if read line <test; then echo $line; fi done

# in another shell 
echo 'hi there'

# notice 'hi there' being printed in the first shell

并在fifo上收听大小。

您可能应该使用gnu并行:

find . -maxdepth 1 -type f | parallel --gnu 'wc -l' | awk 'BEGIN {n=0} {n += $1} END {print n}'
或者并行模式下的xargs:

find . -maxdepth 1 -type f | xargs -n1 -P4 wc -l | awk 'BEGIN {n=0} {n += $1} END {print n}'
如果这不符合您的需要,另一个选择是写入临时文件。如果不想写入磁盘,只需写入/dev/shm即可。这是大多数Linux系统上的ramdisk

#!/bin/bash

declare -a temp_files

count=0
for f in *
do
  if [[ -f "$f" ]]; then
    temp_files[$count]="$(mktemp /dev/shm/${f}-XXXXXX)"
    ((count++))
  fi
done

count=0
for f in *
do
  if [[ -f "$f" ]]; then
    cat "$f" | wc -l > "${temp_files[$count]}" &
    ((count++))
  fi
done

wait

cat "${temp_files[@]}" | awk 'BEGIN {n=0} {n += $1} END {print n}'

for tf in "${temp_files[@]}"
do
  rm "$tf"
done

顺便说一下,这可以看作是一个map reduce,wc进行映射,awk进行缩减。

我认为这将创建一个名为“3”的文件。我正在尝试不写入disk.find-maxdepth 1-type f | xargs-n1-P4 wc-l | awk'BEGIN{n=0}{n+=1}END{print n}工作得非常完美。但我选择了/dev/shm,因为我喜欢有一个动态的后台进程数。您可能需要小心一点,如果您有1000个文件,最终将有1000个进程,这可能会使您的机器陷入困境。这需要一些额外的工作来确保进程数量的限制。我会,现在我有10个文件,大小大约为20-30GB。
#!/bin/bash

declare -a temp_files

count=0
for f in *
do
  if [[ -f "$f" ]]; then
    temp_files[$count]="$(mktemp /dev/shm/${f}-XXXXXX)"
    ((count++))
  fi
done

count=0
for f in *
do
  if [[ -f "$f" ]]; then
    cat "$f" | wc -l > "${temp_files[$count]}" &
    ((count++))
  fi
done

wait

cat "${temp_files[@]}" | awk 'BEGIN {n=0} {n += $1} END {print n}'

for tf in "${temp_files[@]}"
do
  rm "$tf"
done