[笑话]今天我在公司的电脑上实验了代码:(){ :|: ; }; :
- cnkilior
- 论坛版主
- 帖子: 4984
- 注册时间: 2007-08-05 17:40
[笑话]今天我在公司的电脑上实验了代码:(){ :|: ; }; :
结果是显然的。
---
可能是我笔误还是别的,我虽然看出来了这段代码的结构,不知怎么的:不能作为一个单词。于是就运行了这段代码。然后ssh端就不相应了,我旁边的人也不相应了!不过还好我ctrl-c速度快,没有造成太多影响!服务器连重启都没有!
--------
分析这段代码的结构:
这段代码看起来很复杂,其实就是函数定义,递归调用。这里只是使用了一个奇怪的名字作为函数名“:”,但不一定所用的bash都能支持这个字符作为函数名,我记得":"代表一个空语句,相当于python里的pass。
把:替换为a就非常清楚了a(){ a|a ; }; a
--
递归调用使用了管道,其实只是 fork了一个新的进程。但根据程序流程,根本不会运行管道对面的东西。ctrl-c(or kill)之后也是不会运行的(broken pipe)。如果换成 || ,即使非正常退出也会重新生成进程。
---
: () { : || : ; }; :
如果能运行的话会更狠!(未经测试)(拒绝各位测试)[/code]
---
可能是我笔误还是别的,我虽然看出来了这段代码的结构,不知怎么的:不能作为一个单词。于是就运行了这段代码。然后ssh端就不相应了,我旁边的人也不相应了!不过还好我ctrl-c速度快,没有造成太多影响!服务器连重启都没有!
--------
分析这段代码的结构:
这段代码看起来很复杂,其实就是函数定义,递归调用。这里只是使用了一个奇怪的名字作为函数名“:”,但不一定所用的bash都能支持这个字符作为函数名,我记得":"代表一个空语句,相当于python里的pass。
把:替换为a就非常清楚了a(){ a|a ; }; a
--
递归调用使用了管道,其实只是 fork了一个新的进程。但根据程序流程,根本不会运行管道对面的东西。ctrl-c(or kill)之后也是不会运行的(broken pipe)。如果换成 || ,即使非正常退出也会重新生成进程。
---
: () { : || : ; }; :
如果能运行的话会更狠!(未经测试)(拒绝各位测试)[/code]
- BigSnake.NET
- 帖子: 12522
- 注册时间: 2006-07-02 11:16
- 来自: 廣州
- 联系:
- bones7456
- 帖子: 8495
- 注册时间: 2006-04-12 20:05
- 来自: 杭州
- 联系:
- sinyadvan
- 帖子: 724
- 注册时间: 2008-04-02 15:36
- 来自: O_O
- yang
- 帖子: 190
- 注册时间: 2007-10-18 19:57
- cnkilior
- 论坛版主
- 帖子: 4984
- 注册时间: 2007-08-05 17:40
- sinyadvan
- 帖子: 724
- 注册时间: 2008-04-02 15:36
- 来自: O_O
管道前后的命令是同时执行的。若有多个管道,只有第一个管道前后的命令同时执行。cnkilior 写了:管道前面的东西没有执行完,管道对面的东西不会执行吧?BigSnake.NET 写了:管道的版本显然比 || 的更狠
其实这个代码威力就在于管道,管道使得两边的命令同时进行,fork 出的进程成几何级数增加 ( 1 -> 2 ->4 ->8 ..)
而 || 的话,只是简单的递归罢了
------
奇怪了,和我想的不一样!
管道前面的东西没有执行完,管道对面的东西还是会执行@!
---
明白了,只要管道建立了,对面的就会运行,如果对面的程序收到EOF就会broken pipe!(并且终止程序)
在这个代码中永远没有EOF管道,对面的程序一直运行。果然狠!
^o^ && O_O && ^_^
One World|One Dream|One Piece
愛 ^_^ 這個 美麗的世界O_O
本公司专治各种不服、不爽、谩骂、挑衅。
One World|One Dream|One Piece
愛 ^_^ 這個 美麗的世界O_O
本公司专治各种不服、不爽、谩骂、挑衅。
- cnkilior
- 论坛版主
- 帖子: 4984
- 注册时间: 2007-08-05 17:40
- bones7456
- 帖子: 8495
- 注册时间: 2006-04-12 20:05
- 来自: 杭州
- 联系:
- cnkilior
- 论坛版主
- 帖子: 4984
- 注册时间: 2007-08-05 17:40
代码: 全选
( 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
但要是后一个程序不要stdin就“提前”运行了
- BigSnake.NET
- 帖子: 12522
- 注册时间: 2006-07-02 11:16
- 来自: 廣州
- 联系:
- 百草谷居士
- 帖子: 4025
- 注册时间: 2006-02-10 16:36
- 系统: debian12/xubuntu2404
- cnkilior
- 论坛版主
- 帖子: 4984
- 注册时间: 2007-08-05 17:40
- bones7456
- 帖子: 8495
- 注册时间: 2006-04-12 20:05
- 来自: 杭州
- 联系:
- sinyadvan
- 帖子: 724
- 注册时间: 2008-04-02 15:36
- 来自: O_O
我的理解是错的,BigSnake.NET是对的。
这是我认真看完书后新的理解:
1.bash遇到管道符时先调用pipe()创建管道再调用fork()发起两个subshell执行“|”两边的命令。
2.管道两边的命令是并行的,但是管道的通信是半双工、顺序的。
3.通过内核缓冲区按先进先出的方式传输数据,管道一端顺序地写入数据,另一端顺序地读入数据。数据只读一次,之后被释放。
4.可以通过重定向符(>、<、>>、<<)改变通信路径。
这是我认真看完书后新的理解:
1.bash遇到管道符时先调用pipe()创建管道再调用fork()发起两个subshell执行“|”两边的命令。
2.管道两边的命令是并行的,但是管道的通信是半双工、顺序的。
3.通过内核缓冲区按先进先出的方式传输数据,管道一端顺序地写入数据,另一端顺序地读入数据。数据只读一次,之后被释放。
4.可以通过重定向符(>、<、>>、<<)改变通信路径。
^o^ && O_O && ^_^
One World|One Dream|One Piece
愛 ^_^ 這個 美麗的世界O_O
本公司专治各种不服、不爽、谩骂、挑衅。
One World|One Dream|One Piece
愛 ^_^ 這個 美麗的世界O_O
本公司专治各种不服、不爽、谩骂、挑衅。