我有一个全局变量foo =“some value”和后台进程back_func,我想要后台进程访问$ foo并修改其值,这可以通过主进程看到。它类似于以下内容:
#!/bin/bash foo=0 function back_func { foo=$(($foo+1)) echo "back $foo" } (back_func) & echo "global $foo"
上述脚本的结果是
global 0 back 1
会合
如果你想有两个独立的过程可以沟通,你必须在一个两个过程可以达到的地方放置一个rendez-vous。
这可以是一个简单的文件,一个fifo管道,一个unix套接字,一个TCP套接字或者其他(Rexx端口)。
Bash没有相当于rexx端口,所以有一些示例,使用rendez-vous文件,在我的Linux上工作。
我正在使用共享内存/ dev / shm来减少磁盘负载。
简单的计数器样品
$ back_func() { while :;do echo $(($(</dev/shm/foo)+1)) >/dev/shm/foo; sleep .3; done; }
让我们玩
$ echo 1 >/dev/shm/foo $ back_func & $ echo $(</dev/shm/foo) 4 $ echo $(</dev/shm/foo) 21
比现在停止:
$ fg back_func ^C
要么
$ kill $! $ [1]+ Terminated back_func
多个变量
对于有很多vars,可以通过一个很好的方式:
$ back_func() { declare -A MYGLOBAL local vars while :; do ((MYGLOBAL["counter"]++)) IFS=\ / read -a vars <<< "$(</proc/uptime) $(</proc/loadavg)" MYGLOBAL["uptime"]=$vars MYGLOBAL["idle"]=${vars[1]} MYGLOBAL["l01m"]=${vars[2]} MYGLOBAL["l05m"]=${vars[3]} MYGLOBAL["l15m"]=${vars[4]} MYGLOBAL["active"]=${vars[5]} MYGLOBAL["procs"]=${vars[6]} MYGLOBAL["lpid"]=${vars[7]} MYGLOBAL["rand"]=$RANDOM MYGLOBAL["crt"]=$SECONDS declare -p MYGLOBAL > /dev/shm/foo sleep 1 done }
然后
$ back_func & [1] 27429 $ . /dev/shm/foo $ echo ${MYGLOBAL['counter']} 5 $ echo ${MYGLOBAL['lpid']} 27432
从那里,为什么不:
$ dumpMyGlobal() { . /dev/shm/foo printf "%8s " ${!MYGLOBAL[@]} echo printf "%8s " ${MYGLOBAL[@]} echo } $ dumpMyGlobal l15m uptime crt procs lpid active rand idle l05m counter l01m 0.42 13815568.06 95 554 649 1 31135 21437004.95 0.38 73 0.50 $ dumpMyGlobal l15m uptime crt procs lpid active rand idle l05m counter l01m 0.41 13815593.29 120 553 727 2 3849 21437046.41 0.35 98 0.33
要么
$ dumpMyGlobal() { . /dev/shm/foo sort <( paste <( printf "%-12s\n" ${!MYGLOBAL[@]} ) <(printf "%s\n" ${MYGLOBAL[@]}) ) } $ dumpMyGlobal active 1 counter 297 crt 337 idle 21435798.86 l01m 0.40 l05m 0.44 l15m 0.45 lpid 30418 procs 553 rand 7328 uptime 13814820.80
使用快照获取变量
最后getMyGlobalVar函数
$ declare -A MYGLOBALLOCK # snapshot variable $ getMyGlobalVar () { local i sync=false [ "$1" == "--sync" ] && shift && sync=true if [ -z "${MYGLOBALLOCK[*]}" ] || $sync; then . /dev/shm/foo for i in ${!MYGLOBAL[@]} do MYGLOBALLOCK[$i]=${MYGLOBAL[$i]} done fi echo ${MYGLOBALLOCK[$1]} }
将需要–sync标志来重新读取rendez-vous,以便让您查看同一快照中的每个字段。
$ getMyGlobalVar --sync idle 362084.12 $ getMyGlobalVar idle 362084.12 $ getMyGlobalVar rand 1533 $ getMyGlobalVar rand 1533 $ getMyGlobalVar --sync rand 43256 $ getMyGlobalVar idle 362127.63
完全可用的样品:
有一个完整的示例:bash_ipc_demo
你可以使用:
wget http://f-hauri.ch/vrac/bash_ipc_demo source bash_ipc_demo back_func help Usage: bash [-q] [start|stop|restart|status|get|dump|help] back_func status Background loop function is not running. back_func start back_func status Background loop function (19939) is running.
从那里,如果您在另一个终端中发送bash_ipc_demo,则可以将其列入其中。
你甚至可以关闭第一个终端。
back_func dump backFunc_count 13 backFunc_now 2016-04-06 17:03:19 backFunc_pid 19939 backFunc_running yes backFunc_start 2016-04-06 17:03:07 cpu_numcores 2 loadavg_15min 0.44 loadavg_1min 0.66 loadavg_5min 0.54 loadavg_active 1 loadavg_last_pid 20005 loadavg_process 650 random 3714432 uptime_idle 425499.43 uptime_up 495423.53 uptime_usage1sec 9.90 uptime_usage 57.06 uptime_useGraph 57.06 8.91 7.50 6.93 12.00 9.41 7.84 9.90 7.50 11.88 7.92 9.31 9.90
那么你可以得到一个值
back_func get backFunc_pid newVar echo $newVar 19939
或构建最后一分钟图:
back_func get uptime_useGraph vars;path="M0,0";x=0;for y in $vars;do printf -v step "L%.2f,%.2f L%.2f %.2f " $((x++*3)) $y $[3*x] $y path+=" $step" done;path+=" L$((3*x)),0 z";echo "<svg width=\"180\" height=\"100\"> <rect style=\"fill: #DDD;\" width=\"180\" height=\"100\"></rect> <path style=\"fill: #08B;\" transform=\"matrix(1,-1,100)\" d=\"$path\"></path></svg>" | inkscape -z --export-png=lastMinute.png /dev/stdin;eog lastMinute.png ** (inkscape:22147): WARNING **: Format autodetect Failed. The file is being opened as SVG. Background RRGGBBAA: ffffff00 Area 0:0:180:100 exported to 180 x 100 pixels (90 dpi) Bitmap saved as: lastMinute.png
然后:
back_func stop back_func get backFunc_end 2016-04-06 17:16:08