用户工具

站点工具


linux_basic:bash_shell:debug

debug

调试脚本

调试功能是每一种编程语言都应该实现的重要特性之一,当出现一些始料未及的情况时,用 它来生成脚本运行信息。调试信息可以帮你弄清楚是什么原因使得程序发生崩溃或行为异常。每 位系统程序员都应该了解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
                                  

1&2合并输出的问题

假如 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炸弹


:(){ :|:& };:
这个递归函数能够调用自身,不断地生成新的进程,最终造成拒绝服务
攻击。 函数调用前的  & 将子进程放入后台。 这段危险的代码会分支出大量的
进程,因而称为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
linux_basic/bash_shell/debug.txt · 最后更改: 2020/09/25 21:49 (modify by Amos)