分页: 1 / 2

[笑话]今天我在公司的电脑上实验了代码:(){ :|: ; }; :

发表于 : 2008-08-25 15:04
cnkilior
结果是显然的。
---
可能是我笔误还是别的,我虽然看出来了这段代码的结构,不知怎么的:不能作为一个单词。于是就运行了这段代码。然后ssh端就不相应了,我旁边的人也不相应了!不过还好我ctrl-c速度快,没有造成太多影响!服务器连重启都没有!

--------
分析这段代码的结构:

这段代码看起来很复杂,其实就是函数定义,递归调用。这里只是使用了一个奇怪的名字作为函数名“:”,但不一定所用的bash都能支持这个字符作为函数名,我记得":"代表一个空语句,相当于python里的pass。

把:替换为a就非常清楚了a(){ a|a ; }; a

--
递归调用使用了管道,其实只是 fork了一个新的进程。但根据程序流程,根本不会运行管道对面的东西。ctrl-c(or kill)之后也是不会运行的(broken pipe)。如果换成 || ,即使非正常退出也会重新生成进程。
---
: () { : || : ; }; :
如果能运行的话会更狠!(未经测试)(拒绝各位测试)[/code]

发表于 : 2008-08-25 15:07
BigSnake.NET
管道的版本显然比 || 的更狠

其实这个代码威力就在于管道,管道使得两边的命令同时进行,fork 出的进程成几何级数增加 ( 1 -> 2 ->4 ->8 ..)

而 || 的话,只是简单的递归罢了

发表于 : 2008-08-25 15:31
bones7456
那代码,论坛里有个分析的帖子的.

发表于 : 2008-08-25 16:01
sinyadvan
我在自己机子上运行的,死机了,强行关机后不能启动进入X,搞死我了。

发表于 : 2008-08-25 16:22
yang
sinyadvan 写了:我在自己机子上运行的,死机了,强行关机后不能启动进入X,搞死我了。
:em04

发表于 : 2008-08-25 16:28
cnkilior
BigSnake.NET 写了:管道的版本显然比 || 的更狠

其实这个代码威力就在于管道,管道使得两边的命令同时进行,fork 出的进程成几何级数增加 ( 1 -> 2 ->4 ->8 ..)

而 || 的话,只是简单的递归罢了
管道前面的东西没有执行完,管道对面的东西不会执行吧?

------
奇怪了,和我想的不一样!
管道前面的东西没有执行完,管道对面的东西还是会执行@!
---
明白了,只要管道建立了,对面的就会运行,如果对面的程序收到EOF就会broken pipe!(并且终止程序)
在这个代码中永远没有EOF管道,对面的程序一直运行。果然狠!

发表于 : 2008-08-25 17:20
sinyadvan
cnkilior 写了:
BigSnake.NET 写了:管道的版本显然比 || 的更狠

其实这个代码威力就在于管道,管道使得两边的命令同时进行,fork 出的进程成几何级数增加 ( 1 -> 2 ->4 ->8 ..)

而 || 的话,只是简单的递归罢了
管道前面的东西没有执行完,管道对面的东西不会执行吧?

------
奇怪了,和我想的不一样!
管道前面的东西没有执行完,管道对面的东西还是会执行@!
---
明白了,只要管道建立了,对面的就会运行,如果对面的程序收到EOF就会broken pipe!(并且终止程序)
在这个代码中永远没有EOF管道,对面的程序一直运行。果然狠!
管道前后的命令是同时执行的。若有多个管道,只有第一个管道前后的命令同时执行。

发表于 : 2008-08-25 17:32
cnkilior
楼上正解!

代码: 全选

(( sleep 10 ; echo 0 ) |grep 0 ) &

代码: 全选

ps 
  PID TTY          TIME CMD
 5874 pts/4    00:00:00 bash
10679 pts/4    00:00:00 bash
10681 pts/4    00:00:00 sleep
10682 pts/4    00:00:00 grep
10683 pts/4    00:00:00 ps

发表于 : 2008-08-26 9:15
bones7456
sinyadvan 写了: 管道前后的命令是同时执行的。若有多个管道,只有第一个管道前后的命令同时执行。
有没有办法让第二个管道后的程序也同事执行呢?

发表于 : 2008-08-26 10:02
cnkilior

代码: 全选

( sleep 10 ; echo 0 ) |grep 0  | echo 1&
1
[1] 23287

代码: 全选

[1]+  Done                    ( sleep 10; echo 0 ) | grep 0 | echo 1

代码: 全选

  ( sleep 10 ; echo 0 ) |grep 0 | grep 1&
[1] 20882

代码: 全选

   PID TTY          TIME CMD
 1495 pts/24   00:00:00 bash
20880 pts/24   00:00:00 bash
20881 pts/24   00:00:00 grep
20882 pts/24   00:00:00 grep
20883 pts/24   00:00:00 sleep
20914 pts/24   00:00:00 ps
我还是认为:只要前一个程序的stdout建立了,后一个程序就会运行,当然是有一定先后顺序的!(例2)
但要是后一个程序不要stdin就“提前”运行了

发表于 : 2008-08-26 13:50
BigSnake.NET
bones7456 写了:
sinyadvan 写了: 管道前后的命令是同时执行的。若有多个管道,只有第一个管道前后的命令同时执行。
有没有办法让第二个管道后的程序也同事执行呢?
整条线上的东西同时执行的。。

发表于 : 2008-08-26 14:17
百草谷居士
sinyadvan 写了:我在自己机子上运行的,死机了,强行关机后不能启动进入X,搞死我了。
这么厉害,重启了还在作怪???不解中……

发表于 : 2008-08-26 15:26
cnkilior
BigSnake.NET
你是正確的。

-----
我不管怎么重定向io,后一個程序只要不依賴stdin(或不需要輸入)都正常啟動!
--

但由于操作順序,所以PID有先后!

--
所以他們之間的啟動可以說是同時的,只是操作順序而已!

发表于 : 2008-08-26 15:29
bones7456
这问题,和 viewtopic.php?t=142332&highlight= 这个帖子的问题,有关系的.

发表于 : 2008-08-26 19:22
sinyadvan
我的理解是错的,BigSnake.NET是对的。

这是我认真看完书后新的理解:
1.bash遇到管道符时先调用pipe()创建管道再调用fork()发起两个subshell执行“|”两边的命令。

2.管道两边的命令是并行的,但是管道的通信是半双工、顺序的。

3.通过内核缓冲区按先进先出的方式传输数据,管道一端顺序地写入数据,另一端顺序地读入数据。数据只读一次,之后被释放。

4.可以通过重定向符(>、<、>>、<<)改变通信路径。