我编写了3个名为s1.sh s2.sh s3.sh的shell脚本。它们具有相同的内容:
#!/bin/ksh
echo $0 $$
和s.sh按顺序调用它们:
#!/bin/sh
echo $0 $$
exec ./s1.sh &
exec ./s2.sh &
exec ./s3.sh &
但结果是无序的:
victor@ThinkPad-Edge:~$ ./s.sh
./s.sh 3524
victor@ThinkPad-Edge:~$ ./s1.sh 3525
./s3.sh 3527
./s2.sh 3526
为什么不是s1 s2然后顺序s3?
如果我删除&在s.sh中:
#!/bin/sh
echo $0 $$
exec ./s1.sh
exec ./s2.sh
exec ./s3.sh
输出:
$ ./s.sh
./s.sh 4022
./s1.sh 4022
缺少s2和s3,为什么?
答案 0 :(得分:4)
他们一直按顺序执行(至少按顺序开始 - 注意id正在递增)。您为3个单独的程序打开3个单独的线程。一个(出于某种原因)比另一个快。如果您想按顺序使用它们,请从exec
中取出&
和exec ./s1.sh &
。
答案 1 :(得分:2)
进程调度程序通过一次运行每个任务的片段,然后快速切换到另一个任务来实现明显的多任务处理。根据系统负载,I / O等待,优先级,调度算法等,几乎同时启动的两个进程可能会获得可用CPU的完全不同的分配。因此,无法保证您的三个进程中的哪一个首先到达echo
语句。
这是非常基本的Unix知识;也许你应该读一本书或在线教程,如果你的意思是认真使用Unix。
如果您需要并行进程以特定顺序执行,请使用锁定机制(信号量,共享内存等)来防止执行代码的特定部分(称为“临界区”),然后再执行另一个。 (但是在shell脚本中这并不容易。如果你不想一直到C,请切换到Python或Perl。如果你可以忍受I / O延迟,可以使用锁文件。)
在第二个示例中,exec
命令将当前进程替换为另一个。因此,s1
完全接管,并且shell永远不会看到启动s2
和s3
的命令。
(这在你的第一个例子中并不明显,因为&
导致shell首先分叉后台进程,基本上使exec
无用。{/ p>
答案 2 :(得分:1)
&
运算符将每个exec
放在后台。实际上,您并行运行所有3个脚本。它们不会保持有序,因为操作系统只要有机会就会执行一些脚本,但它也会执行一堆其他的东西。一个过程可以比其他过程有更多的时间运行,从而使其更快完成。
答案 3 :(得分:0)
缺少s2和s3,为什么?
您不会错过s2
或s3
- s2
和s3
正在替换或子shell中执行(当s.sh
退出时(或被替换) ),它们失去与控制台的通信,导致它们的输出覆盖TTY上的先前输出。
其他答案已经讨论过,s1,s2,s3
全部在替换shell (exec
)或子shell (不包含exec
内执行以及如何删除exec
和&
将强制执行s1,s2,s3
。有两种情况需要讨论。一个exec
存在而另一个不存在的地方。如果存在exec
,则当前shell将被执行的进程替换(如注释中所指出的,父shell被终止)。
如果未使用exec,则在子shell中执行s1,s2,s3
。您没有看到s2
,s3
的输出,因为s.sh
已在s2
之前完成和/或退出,s3
执行删除与控制台的通信(如果你看起来你会看到你显示一个额外的提示,然后是剩余的s(2,3).sh
命令的输出。但是,有一种方法可以在s.sh
退出之前完成它们。使用{{1} }。wait
告诉wait
在完成所有子进程s.sh
之前不要退出。这提供了一个到控制台的输出路径。例如:
s1, s2, and s3
<强>输出:强>
#!/bin/bash
echo $0 $$
exec ./1.sh &
exec ./s2.sh &
exec ./s3.sh &
wait