shell里有队列的概念吗?
我想做一个队列,然后几个后台并行的shell执行队列里的语句,一个shell结束后,马上运行下一个,即使是两个shell同时结束,也要依队列次序取,不能取重复,也不能取漏了,不知有没有好的方法实现.
寂寞烈火 回复于:2005-12-23 22:10:36
1,首先,shell解释脚本就是按照先后顺序逐条解释语句并执行的
2,楼主所言,应该需要用到wait这个shell的builtin
3,shell is not all-purpose ^_^
[ 本帖最后由 寂寞烈火 于 2005-12-23 22:12 编辑 ]
大蚂蚁 回复于:2005-12-23 22:17:01
如果不后台运行的话,shell本来就是按队列运行的
如果要设计队列和堆栈,我想shell应该可以在文件的读写中实现吧?
不过效率肯定是不能和C比的
nees 回复于:2005-12-23 22:42:28
我要运行一个程序P1,P1带一个参数,并且参数需要从1循环到100,当然,我可以写一个shell循环实现,便是效率过于低下,因为是串行的,后一个一定要等前一个执行完才执行,当然也不可能在循环中将这100个带参数的P1全放在后台运行.所以我想做一个并发执行的shell程序,并发度可控制,如用4个后台的shell来调用P1,但是关键是这四个shell的运行不能有冲突,如两个shell同时调用P1,并且参数相同,参数的顺序只能是从1到100,不能重复,不能遗漏,请问该如何实现?
nees 回复于:2005-12-23 22:46:36
实际上我目前已有一个解决方案,但是觉得不是很好,我用到了oracle的序号发生器,第一个shell执行时,取序号1,第二个取序号2,第三个取序号3,第四个取序号4,然后这四个shell中先退出的那个再取序号5,所以传给P1的参数不会重复,也不会遗漏.
大蚂蚁 回复于:2005-12-23 22:49:41
引用:原帖由 nees 于 2005-12-23 22:42 发表
我要运行一个程序P1,P1带一个参数,并且参数需要从1循环到100,当然,我可以写一个shell循环实现,便是效率过于低下,因为是串行的,后一个一定要等前一个执行完才执行,当然也不可能在循环中将这100个带参数的P1全放在后 ...
读文件,写文件啊.
每行提供一个脚本实例运行的参数.
如果读完这个参数就把这个地方标上标记,可以写进去,sed -i 应该可以的.由于写文件会锁文件,而读文件不会,所以建议写完标志位后再检查一下此行,没有问题就提交执行.
另外由于写文件的时候有filelocking,所以建议这四个进程有个监护进程,把由于出错退出的进程再次拉起.
偶的一点点思路,希望有用...
大蚂蚁 回复于:2005-12-23 22:51:06
其实,你的要求没有必要用shell实现,C应该会好一点,在内存中操作这些要远比在shell中好,效率也高很多.
r2007 回复于:2005-12-24 10:27:34
这样如何?
#!/bin/bash
tmpfile=$$.fifo
mkfifo $tmpfile
exec 4<>$tmpfile
rm $tmpfile
{ echo;echo;echo;echo; } >&4
for (( i = 1 ; i <= 100 ; i++ ))
do
read
( ur_command $i; echo >&4 ) &
done <&4
wait
nees 回复于:2005-12-24 18:11:43
楼上的,我在cygwin里执行不了啊,能不能解释一下你的思路?
r2007 回复于:2005-12-24 19:27:15
#!/bin/bash
tmpfile=$$.fifo
mkfifo $tmpfile
exec 4<>$tmpfile
rm $tmpfile #以上工作---开一包间(一楼4号房间)
{ echo;echo;echo;echo; } >&4 #摆一桌麻将,4张椅子
for (( i = 1 ; i <= 100 ; i++ )) #100个赌鬼排队进场
do
read #赌鬼开始抓风,东西南北,拿椅子按次序坐下
( ur_command $i; echo >&4 ) & #开始打牌ing...;bp机响了,是GF的,归还椅子走人
done <&4
wait #等待最后4个赌鬼打完
BTW:木有测试
nees 回复于:2005-12-25 14:17:03
楼主高人啊。
nees 回复于:2005-12-25 20:32:11
我在linux下测试通过。
另外我写了一种变体,对于参数不是连续的也可以适用,请大家指正:
#!/bin/bash
tmpfile=$$.fifo
mkfifo $tmpfile
exec 4<>$tmpfile
rm $tmpfile #以上工作---开一包间(一楼4号房间)
thred=4
seq=(1 2 3 4 5 6 7 8 9 21 22 23 24 25 31 32 33 34 35)
#
{
for (( i = 1;i<=${thred};i++ ))
do
echo;
done
} >&4
for id in ${seq[*]}
do
read
(./ur_command ${id};echo >&4 ) &
done <&4
wait
fallseir 回复于:2006-06-02 14:03:38
#!/bin/bash
tmpfile=$$.fifo #创建管道名称
mkfifo $tmpfile #创建管道
exec 4<>$tmpfile #创建文件标示4,以读写方式操作管道$tmpfile
rm $tmpfile #将创建的管道文件清除
thred=4 #指定并发个数
seq=(1 2 3 4 5 6 7 8 9 21 22 23 24 25 31 32 33 34 35) #创建任务列表
# 为并发线程创建相应个数的占位
{
for (( i = 1;i<=${thred};i++ ))
do
echo; #因为read命令一次读取一行,一个echo默认输出一个换行符,所以为每个线程输出一个占位换行
done
} >&4 #将占位信息写入管道
for id in ${seq[*]} #从任务列表 seq 中按次序获取每一个任务
do
read #读取一行,即fd4中的一个占位符
(./ur_command ${id};echo >&4 ) & #在后台执行任务ur_command 并将任务 ${id} 赋给当前任务;任务执行完后在fd4种写入一个占位符
done <&4 #指定fd4为整个for的标准输入
wait #等待所有在此shell脚本中启动的后台任务完成
exec 4>&- #关闭管道
整个流程中read 和 echo 对fd4的交替写入和读取是并发处理的关键
可以想象 如果read 命令发现fd4中没有数据时 将等待fd4的数据
如果可以自动kill掉超时的子任务就更好了
摘录了一篇 放到了我的blog
http://fallseir.livejournal.com/58761.html
-0====================
飞扬轻狂 http://feed.feedsky.com/fallseir
r2007 回复于:2006-06-02 14:11:02
感谢楼上加注。
UnixLight 回复于:2006-06-02 16:33:29
3楼楼长真牛!
phpman 回复于:2006-06-18 18:15:32
引用:原帖由 fallseir 于 2006-6-2 14:03 发表
#!/bin/bash
tmpfile=$$.fifo #创建管道名称
mkfifo $tmpfile #创建管道
exec 4<>$tmpfile #创建文件标示4,以读写方式操作管道$tmpfile
rm $tmpfile #将创建的管道文件清除
...
exec 4>&- #关闭管道
脚本退出时会自动关闭这个管道吧?
|