调试功能是每一种编程语言都应该实现的重要特性之一,当出现一些始料未及的情况时,用 它来生成脚本运行信息。调试信息可以帮你弄清楚是什么原因使得程序发生崩溃或行为异常。每 位系统程序员都应该了解Bash提供的调试选项
-x 标识将脚本中执行过的每一行都输出到 stdout 。不过,我们也可能只关注脚本某些部分 的命令及参数的打印输出。针对这种情况,可以在脚本中使用 set builtin 来启用或禁止调试 打印。 set –x :在执行时显示参数和命令。 set +x :禁止调试。 set –v :当命令进行读取时显示输入。 set +v :禁止打印输入。 #或者在脚本首行添加参数 #!/bin/bash 改成 #!/bin/bash -xv
#!/bin/bash #文件名: debug.sh for i in {1..6};do set -x echo $i set +x done echo "Script executed" #位于set -x 与set +x之间的信息将输出到屏幕上。 [root@VM_0_5_centos ~]# sh 1.txt + echo 1 1 + set +x + echo 2 2 + set +x + echo 3 3 + set +x + echo 4 4 + set +x + echo 5 5 + set +x + echo 6 6 + set +x Script executed
0 —— stdin (标准输入) 。等效于 /dev/stdin 1 —— stdout (标准输出) 。等效于 /dev/stdout 2 —— stderr (标准错误输出) 等效于 /dev/stderr 空设备:/dev/null 1> = > 1>> = >> #1是默认值,可省略。 < 将文件输入到命令的stdin
假如 stdout(1) 与 stderr(2) 都同时在写入 file.both 的话,则要看它们在写入时否碰到同时竞争的情形了,基本上是“先抢先赢”的原则。
让我们用周星驰式的“慢镜头”来看一下 stdout 与 stderr 同时写入 file.out 的情形好了:
* 第 1, 2, 3 秒为 stdout 写入
* 第 3, 4, 5 秒为 stderr 写入
那么,这时候 stderr 的第 3 秒所写的数据就丢失掉了﹗
要是我们能控制 stderr 必须等 stdout 写完再写,或倒过来,stdout 等 stderr 写完再写,那问题就能解决。
但从技术上,较难掌控的,尤其是 FD 在作“长期性”的写入时…
那,如何解决呢?所谓山不转路转、路不转人转嘛,我们可以换一个思维:将 stderr 导进 stdout 或将 stdout 导进 sterr ,而不是大家在抢同一份档案,不就行了﹗
bingo﹗就是这样啦:
* 2>&1 就是将 stderr 并进 stdout 作输出
* 1>&2 或 >&2 就是将 stdout 并进 stderr 作输出
即,合并之后再输出到文件
于是,前面的错误操作可以改为:
代码:
$ ls my.file no.such.file 1>file.both 2>&1 或 $ ls my.file no.such.file 2>file.both >&2
这样,不就皆大欢喜了吗? 呵~~~
ls + > out.txt ls + 1> out.txt #ls: cannot access +: No such file or directory #该行输出是stderr=2输出到屏幕上。 #ls + 是错误的命令,只有报错,错误输出。 #无标准输出,stdout=1,故out.txt文件为空。 ls 1> out.txt #命令正常输出,输出out.txt 下面的命令中,我们将 stderr 重定向到out.txt: ls + 2> out.txt # 正常运行 #分别输出到不同的文件: cmd 2>stderr.txt 1>stdout.txt #还可以利用下面这个更好的方法将 stderr 转换成 stdout ,使得 stderr 和 stdout都被重定向到同一个文件中: $ cmd 2>&1 output.txt 或者这样: $ cmd &> output.tx #屏蔽输出stderr到屏幕 cmd 2>/dev/null
#同时在屏幕和文件中输出,使用tee命令配合 #tee命令的作用 #tee 接收前面的命令的stdout输出到文件,然后还可以将接收的信息以stdin的形式传递到后面的命令 #注意tee只接收stdout ls | tee -a stdout.txt | cat -n #tee -a参数表示追加输出到文件 #tee命令用于将数据重定向到文件,另一方面还可以提供一份重定向数据的副本作为后续命令的stdin。简单的说就是把数据重定向到给定文件和屏幕上。
$1 是第一个参数。 $2 是第二个参数。 $n 是第n个参数。 "$@" 被扩展成 "$1" "$2" "$3" 等。 "$*" 被扩展成 "$1c$2c$3" ,其中 c 是IFS的第一个字符。 "$@" 要比 "$*" 用得多。由于 "$*" 将所有的参数当做单个字符串,因此它很少被使用。
:(){ :|:& };: 这个递归函数能够调用自身,不断地生成新的进程,最终造成拒绝服务 攻击。 函数调用前的 & 将子进程放入后台。 这段危险的代码会分支出大量的 进程,因而称为Fork炸弹。 上面这段代码要理解起来可不容易。请参阅维基百科http://en.wikipedia. org/wiki/Fork_bomb,那里列出了有关Fork炸弹的细节以及更详细的解释。 可以通过修改配置文件/etc/security/limits.conf来限制可生成的最大进程 数来避开这枚炸弹。
#示例 echo $?; $? 会给出命令 cmd 的返回值。 返回值被称为退出状态。它可用于分析命令执行成功与否。如果命令成功退出,那么退出状 态为0,否则为非0。
可以按照下面的方法检测某个命令是否成功结束: #!/bin/bash #文件名: success_test.sh CMD="command" #command指代你要检测退出状态的目标命令 $CMD if [ $? -eq 0 ];then echo "$CMD executed successfully" else echo "$CMD terminated unsuccessfully" fi