什么是递归函数?
一句话,调用自己的函数称为递归函数!
#!/bin/bash
declare -i count checkoutCount(){
read -p "Enter an count: " count
if [ $count -eq 100 ]; then
echo "Count is 100."
else
if [ $count -gt 100 ]; then
echo "count is greater than 100."
else
echo "count is less than 100."
fi
fi
checkoutCount
}
checkoutCount

结果展示:

经典的递归函数----江湖俗称"fork 炸弹"

可能很多人都曾经听说过 fork 炸弹,它实际上只是一个非常简单的递归程序,程序所做的事情只有一样:不断 fork 一个新进程。由于程序是递归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源。

清单1. bash 中的 fork 炸弹

.(){ .|.& };.

清单2. bash 中的 fork 炸弹的解释

 1 .()

  2 {

  3  .|.& 

  4 }

  5 ;

  6 .

第 1 行说明下面要定义一个函数,函数名为小数点,没有可选参数。

第 2 行表示函数体开始。

第 3 行是函数体真正要做的事情,首先它递归调用本函数,然后利用管道调用一个新进程(它要做的事情也是递归调用本函数),并将其放到后台执行。

第 4 行表示函数体结束。

第 5 行并不会执行什么操作,在命令行中用来分隔两个命令用。从总体来看,它表明这段程序包含两个部分,首先定义了一个函数,然后调用这个函数。

第 6 行表示调用本函数。

对 于函数名,大家可能会有所疑惑,小数点也能做函数名使用吗?毕竟小数点是 shell 的一个内嵌命令,用来在当前 shell 环境中读取指定文件,并运行其中的命令。实际上的确可以,这取决于 bash 对命令的解释顺序。默认情况下,bash 处于非 POSIX 模式,此时对命令的解释顺序如下:

关键字,例如 if、for 等。

别名。别名不能与关键字相同,但是可以为关键字定义别名,例如 end=fi。

特殊内嵌命令,例如 break、continue 等。POSIX 定义的特殊内嵌命令包括:.(小数点)、:(冒号)、break、continue、eval、exec、exit、export、readonly、 return、set、shift、times、trap 和 unset。bash 又增加了一个特殊的内嵌命令 source。

函数。如果处于非 POSIX 模式,bash 会优先匹配函数,然后再匹配内嵌命令。

非特殊内嵌命令,例如 cd、test 等。

脚本和可执行程序。在 PATH 环境变量指定的目录中进行搜索,返回第一个匹配项。

由 于默认情况下,bash 处于非 POSIX 模式,因此 fork 炸弹中的小数点会优先当成一个函数进行匹配。(实际上,Jaromil 最初的设计并没有使用小数点,而是使用的冒号,也能起到完全相同的效果。)要使用 POSIX 模式来运行 bash 脚本,可以使用以下三种方法:

使用 --posix 选项启动 bash。

在运行 bash 之后,执行 set -o posix 命令。

使用 /bin/sh 。

最 后一种方法比较有趣,尽管 sh 在大部分系统上是一个指向 bash 的符号链接,但是它所启用的却是 POSIX 模式,所有的行为都完全遵守 POSIX 规范。在清单 3 给出的例子中,我们可以发现,小数点在默认 bash 中被解释成一个函数,能够正常执行;但是在 sh 中,小数点却被当作一个内嵌命令,因此调用函数时会被认为存在语法错误,无法正常执行。

清单3. bash 与 sh 对命令匹配顺序的区别

[root@localhost ~]# ls -l /bin/bash /bin/sh

-rwxr-xr-x 1 root root 735144 2007-08-31 22:20 /bin/bash

lrwxrwxrwx 1 root root      4 2007-12-18 13:26 /bin/sh -> bash

[root@localhost ~]# echo $SHELL

/bin/bash

[root@localhost ~]# .() { echo hello; } ; .

hello

[root@localhost ~]# sh

sh-3.2# echo $SHELL

/bin/bash

sh-3.2# .() { echo hello; } ; .

sh: `.': not a valid identifier

sh: .: filename argument required

.: usage: . filename [arguments]

sh-3.2#

一旦运行清单 1 给出的 fork 炸弹,会以2的指数次幂的速度不断产生新进程,这会导致系统资源会被迅速耗光,最终除非重新启动机器,否则基本上就毫无办法了。为了防止这会造成太大的损 害,我们可以使用 ulimit 限制每个用户能够创建的进程数,如清单 4 所示。

清单4. 限制用户可以创建的进程数

[root@localhost ~]# ulimit -u 128

[root@localhost ~]# ulimit -a

core file size          (blocks, -c) 0

data seg size           (kbytes, -d) unlimited

max nice                        (-e) 20

file size               (blocks, -f) unlimited

pending signals                 (-i) unlimited

max locked memory       (kbytes, -l) unlimited

max memory size         (kbytes, -m) unlimited

open files                      (-n) 1024

pipe size            (512 bytes, -p) 8

POSIX message queues     (bytes, -q) unlimited

max rt priority                 (-r) unlimited

stack size              (kbytes, -s) 8192

cpu time               (seconds, -t) unlimited

max user processes              (-u) 128

virtual memory          (kbytes, -v) unlimited

file locks                      (-x) unlimited

[root@localhost ~]# .() { .|.& } ; .

[1] 6152

[root@localhost ~]# bash: fork: Resource temporarily unavailable

bash: fork: Resource temporarily unavailable

bash: fork: Resource temporarily unavailable

在清单 4 中,我们将用户可以创建的最大进程数限制为 128,执行 fork 炸弹会迅速 fork 出大量进程,此后会由于资源不足而无法继续执行。

最新文章

  1. 随机生成验证码import random
  2. elasticsearch同义词及动态更新
  3. POJ 1244 Slots of Fun(计算几何)
  4. UITableViewCell 左滑删除
  5. hibernate Disabling contextual LOB creation as connection was null
  6. 关于Latex中插入Visio图片文字不显示的问题
  7. Mybatis报错:Parameter 'list' not found. Available parameters are [groupList, param1]
  8. Springboot入门之分布式事务管理
  9. ELK快速搭建日志平台
  10. Java实现AES加密,异常java.security.InvalidKeyException: Illegal key size 的解决
  11. java 获取当前系统可用字体名称
  12. python 阿狸的进阶之路(5)
  13. 简述项目中优化sql的方法,从哪些方面,sql语句性能如何分析?
  14. ZOJ 3985 - String of CCPC - [字符串处理]
  15. 20165310_Exp2实验三《敏捷开发与XP实践》
  16. python3:cmd运行python脚本,提示 No module named 'xxx'
  17. 01-html和head介绍
  18. js实现unicode码字符串与utf8字节数据互转
  19. xml DTD中的ELEMENT和ATTLIST
  20. Http:UTF-8与GB2312之间的关系

热门文章

  1. [Vue] Update Attributes, Classes and Styles in Vue.js with v-bind
  2. Android的NDK开发(2)————利用Android NDK编写一个简单的HelloWorld
  3. SpringMVC ModelAndView跳转失效
  4. js进阶 10-4 jquery中基础选择器有哪些
  5. Lucene + Pinyin4J 提供首字母搜索(——)
  6. ITFriend创业败局(序):简要概述我的第一次创业经历
  7. [GeekBand] C++ 基础知识之 The Big Three
  8. Swift学习——Swift解释具体的基础(六)
  9. TensorFlow 学习(七) — 常用函数 api、tf.nn 库
  10. WebHost failed to process a request.Memory gates checking failed because the free memory (140656640 bytes) is less than 5% of total memory