如何在 Shell 脚本中跟踪调试命令的执行

在 shell 脚本调试系列 中,本文将解释第三种 shell 脚本调试模式,即 shell 跟踪,并查看一些示例来演示它如何工作以及如何使用它。

本系列的前面部分清晰地阐明了另外两种 shell 脚本调试模式:详细模式和语法检查模式,并用易于理解的例子展示了如何在这些模式下启用 shell 脚本调试。

  1. 如何在 Linux 中启用 Shell 脚本的调试模式
  2. 如何在 Shell 脚本中执行语法检查调试模式

shell 跟踪简单的来说就是跟踪 shell 脚本中的命令的执行。要打开 shell 跟踪,请使用 -x 调试选项。

这会让 shell 在终端上显示所有执行的命令及其参数。

我们将使用下面的 sys_info.sh shell 脚本,它会简要地打印出你的系统日期和时间、登录的用户数和系统的运行时间。不过,脚本中包含我们需要查找和更正的语法错误。


  1. #!/bin/bash
  2. # script to print brief system info
  3. ROOT_ID="0"
  4. DATE=`date`
  5. NO_USERS=`who | wc -l`
  6. UPTIME=`uptime`
  7. check_root(){
  8. if [ "$UID" -ne "$ROOT_ID" ]; then
  9. echo "You are not allowed to execute this program!"
  10. exit 1;
  11. }
  12. print_sys_info(){
  13. echo "System Time : $DATE"
  14. echo "Number of users: $NO_USERS"
  15. echo "System Uptime : $UPTIME
  16. }
  17. check_root
  18. print_sys_info
  19. exit 0

保存文件并执行脚本。脚本只能用 root 用户运行,因此如下使用 sudo 命令运行:


  1. $ chmod +x sys_info.sh
  2. $ sudo bash -x sys_info.sh

shell 跟踪 - 显示脚本中的错误

从上面的输出我们可以观察到,首先执行命令,然后其输出做为一个变量的值。

例如,先执行 date,其输出做为变量 DATE 的值。

我们可以执行语法检查来只显示其中的语法错误,如下所示:


  1. $ sudo bash -n sys_info.sh

脚本中语法检查

如果我们审视这个 shell 脚本,我们就会发现 if 语句缺少了封闭条件的 fi 关键字。因此,让我们加上它,新的脚本应该看起来像这样:


  1. #!/bin/bash
  2. #script to print brief system info
  3. ROOT_ID="0"
  4. DATE=`date`
  5. NO_USERS=`who | wc -l`
  6. UPTIME=`uptime`
  7. check_root(){
  8. if [ "$UID" -ne "$ROOT_ID" ]; then
  9. echo "You are not allowed to execute this program!"
  10. exit 1;
  11. fi
  12. }
  13. print_sys_info(){
  14. echo "System Time : $DATE"
  15. echo "Number of users: $NO_USERS"
  16. echo "System Uptime : $UPTIME
  17. }
  18. check_root
  19. print_sys_info
  20. exit 0

再次保存文件并以 root 执行,同时做语法检查:


  1. $ sudo bash -n sys_info.sh

在 shell 脚本中执行语法检查

上面的语法检查操作的结果仍然显示在脚本的第 21 行还有一个错误。所以,我们仍然要纠正一些语法。

再一次分析脚本,会发现第 21 行的错误是由于在 print_sys_info 函数内最后一个 echo 命令中没有闭合双引号 "

我们将在 echo 命令中添加闭合双引号并保存文件。修改过的脚本如下:


  1. #!/bin/bash
  2. #script to print brief system info
  3. ROOT_ID="0"
  4. DATE=`date`
  5. NO_USERS=`who | wc -l`
  6. UPTIME=`uptime`
  7. check_root(){
  8. if [ "$UID" -ne "$ROOT_ID" ]; then
  9. echo "You are not allowed to execute this program!"
  10. exit 1;
  11. fi
  12. }
  13. print_sys_info(){
  14. echo "System Time : $DATE"
  15. echo "Number of users: $NO_USERS"
  16. echo "System Uptime : $UPTIME"
  17. }
  18. check_root
  19. print_sys_info
  20. exit 0

现在再一次检查语法。


  1. $ sudo bash -n sys_info.sh

上面的命令不会产生任何输出,因为我们的脚本语法上正确。我们也可以再次跟踪脚本执行,它应该工作得很好:


  1. $ sudo bash -x sys_info.sh

跟踪 shell 脚本执行

现在运行脚本。


  1. $ sudo ./sys_info.sh

用 shell 脚本显示日期、时间和运行时间

shell 跟踪执行的重要性

shell 脚本跟踪可以帮助我们识别语法错误,更重要的是识别逻辑错误。例如,在 sys_info.sh shell 脚本中的 check_root 函数,它用于确定用户是否为 root,因为脚本只允许由超级用户执行。


  1. check_root(){
  2. if [ "$UID" -ne "$ROOT_ID" ]; then
  3. echo "You are not allowed to execute this program!"
  4. exit 1;
  5. fi
  6. }

这里的魔法是由 if 语句表达式 ["$ UID" -ne "$ ROOT_ID"] 控制的,一旦我们不使用合适的数字运算符(示例中为 -ne,这意味着不相等),我们最终可能会出一个逻辑错误。

假设我们使用 -eq (意思是等于),这将允许任何系统用户以及 root 用户运行脚本,因此是一个逻辑错误。


  1. check_root(){
  2. if [ "$UID" -eq "$ROOT_ID" ]; then
  3. echo "You are not allowed to execute this program!"
  4. exit 1;
  5. fi
  6. }

注意:我们在本系列开头介绍过,set 这个 shell 内置命令可以在 shell 脚本的特定部分激活调试。

因此,下面的行将帮助我们通过跟踪脚本的执行在其中找到这个逻辑错误:

具有逻辑错误的脚本:


  1. #!/bin/bash
  2. #script to print brief system info
  3. ROOT_ID="0"
  4. DATE=`date`
  5. NO_USERS=`who | wc -l`
  6. UPTIME=`uptime`
  7. check_root(){
  8. if [ "$UID" -eq "$ROOT_ID" ]; then
  9. echo "You are not allowed to execute this program!"
  10. exit 1;
  11. fi
  12. }
  13. print_sys_info(){
  14. echo "System Time : $DATE"
  15. echo "Number of users: $NO_USERS"
  16. echo "System Uptime : $UPTIME"
  17. }
  18. #turning on and off debugging of check_root function
  19. set -x ; check_root; set +x ;
  20. print_sys_info
  21. exit 0

保存文件并调用脚本,在输出中,我们可以看到一个普通系统用户可以在未 sudo 的情况下运行脚本。 这是因为 USER_ID 的值为 100,不等于为 0 的 root 的 ROOT_ID 。


  1. $ ./sys_info.sh

Run Shell Script Without Sudo

原文发布时间为:2017-01-15

本文来自合作伙伴“Linux中国”

时间: 2024-11-01 17:43:17

如何在 Shell 脚本中跟踪调试命令的执行的相关文章

如何在Shell脚本中跟踪调试命令的执行

在 shell 脚本调试系列 中,本文将解释第三种 shell 脚本调试模式,即 shell 跟踪,并查看一些示例来演示它如何工作以及如何使用它. 本系列的前面部分清晰地阐明了另外两种 shell 脚本调试模式:详细模式和语法检查模式,并用易于理解的例子展示了如何在这些模式下启用 shell 脚本调试. 如何在 Linux 中启用 Shell 脚本的调试模式 如何在 Shell 脚本中执行语法检查调试模式 shell 跟踪简单的来说就是跟踪 shell 脚本中的命令的执行.要打开 shell 跟

如何在shell脚本中使用变量

如何在shell脚本中使用变量 在每种编程语言中,变量都扮演了一个重要的角色.在Linux shell脚本编程中,我们使用两种类型的变量:系统定义的变量和用户定义的变量. shell脚本中的变量是用来调用一个数值或者字符值的手段.与正规的编程语言不同的是,shell脚本不要求你去为变量声明一个类型. 在本文中,我们将讨论shell脚本编程中的变量及其类型,以及如何设置和使用这些变量. 系统定义的变量: 这些变量由操作系统(Linux)自身创建并维护,通常它们以大写字母定义,我们可以通过命令"$

如何在Shell脚本中执行语法检查调试模式

我们开启了 Shell 脚本调试系列文章,先是解释了不同的调试选项,下面介绍如何启用 Shell 调试模式. 写完脚本后,建议在运行脚本之前先检查脚本中的语法,而不是查看它们的输出以确认它们是否正常工作. 在本系列的这一部分,我们将了解如何使用语法检查调试模式.记住我们之前在本系列的第一部分中解释了不同的调试选项,在这里,我们将使用它们来执行脚本调试. 启用 verbose 调试模式 在进入本指导的重点之前,让我们简要地探索下 verbose 模式.它可以用 -v 调试选项来启用,它会告诉 sh

如何在 Shell 脚本中执行语法检查调试模式

我们开启了 Shell 脚本调试系列文章,先是解释了不同的调试选项,下面介绍如何启用 Shell 调试模式. 写完脚本后,建议在运行脚本之前先检查脚本中的语法,而不是查看它们的输出以确认它们是否正常工作. 在本系列的这一部分,我们将了解如何使用语法检查调试模式.记住我们之前在本系列的第一部分中解释了不同的调试选项,在这里,我们将使用它们来执行脚本调试. 启用 verbose 调试模式 在进入本指导的重点之前,让我们简要地探索下 verbose 模式.它可以用 -v 调试选项来启用,它会告诉 sh

Shell脚本中实现切换用户并执行命令操作_linux shell

今天公司同事来找到我说要在服务器上用另外一个用户执行python脚本,但设置到crontab里却老是root用户来执行,为了省事我就想了一个偷懒的办法,就是用shell脚本切换到那个用户,然后去执行那个python脚本.好了,这篇文章我只演示怎么用shell脚本切换到其他用户执行命令. 系统:centos 5.x 脚本内容: cat test.sh 复制代码 代码如下: #!/bin/bash su - test <<EOF pwd; exit; EOF 执行结果图: 当然也可以用下面的命令来

如何在shell脚本中判断文件或者文件夹是否存在?

1:查找文件夹 如果文件夹存在,则打印一句存在,否则打印不存在 这里的话可以自由加一些指令. if [ test -d 文件夹名称 ] ; then echo "文件夹存在!" else echo "文件夹不存在!" fi 2:查找文件 如果文件存在,则打印一句存在,否则打印不存在 这里的话也可以自由加一些指令. if [ -f file.txt ]; then echo "文件存在!" else echo "文件不存在!"

Shell脚本中获取进程ID的方法

 这篇文章主要介绍了Shell脚本中获取进程ID的方法,我想要知道运行中脚本子shell的进程id,我该如何在shell脚本中得到PID,阅读本文即可找到你想要答案,需要的朋友可以参考下     提问: 我想要知道运行中脚本子shell的进程id.我该如何在shell脚本中得到PID. 当我在执行shell脚本时,它会启动一个叫子shell的进程.作为主shell的子进程,子shell将shell脚本中的命令作为批处理运行(因此称为"批处理进程"). 在某些情况下,你也许想要知道运行中

Shell脚本中获取进程ID的方法_linux shell

提问: 我想要知道运行中脚本子shell的进程id.我该如何在shell脚本中得到PID. 当我在执行shell脚本时,它会启动一个叫子shell的进程.作为主shell的子进程,子shell将shell脚本中的命令作为批处理运行(因此称为"批处理进程"). 在某些情况下,你也许想要知道运行中的子shell的PID.这个PID信息可以在不同的情况下使用.比如,你可以使用shell脚本的PID在/tmp下创建一个唯一的临时文件.有时侯脚本需要检测所有运行的进程,它可以从进程列表中排除自身

shell命令行参数-Linuxshell脚本中调用可执行程序命令行参数出现丢失错误

问题描述 Linuxshell脚本中调用可执行程序命令行参数出现丢失错误 #!/bin/bash If [$1 == "-i"] then TM_demo $1 $2 fi If [$1 == "-f"] then TM_demo $1 $2 $3 $4 fi 在linux执行的时候./a.sh -f data,出现 [:丢失了"]",大神帮帮忙! 解决方案 [和]不是shell的meta character,所以需要跟其它标识符用blank/s