• 有的,那就是使用shell的执行选项,下面将介绍一些常用选项的用法:-n 只读取shell脚本,但不实际执行-x 进入跟踪方式,显示所执行的每一条命令-c "string" 从strings中读取命令"-n"可用于测试...

    我们在前面介绍的调试手段是通过修改shell脚本的源代码,从其输出相关的调试信息来定位错误的,那有没有不修改源代码来调试shell脚本的方法呢?有的,那就是使用shell的执行选项,下面将介绍一些常用选项的用法:

    -n 只读取shell脚本,但不实际执行
    -x 进入跟踪方式,显示所执行的每一条命令
    -c "string" strings中读取命令

    "-n"可用于测试shell脚本是否存在语法错误,但不会实际执行命令。shell脚本编写完成之后,实际执行之前,首先使用"-n"选项来测试脚本是否存在语法错误是一个很好的习惯。因为某些shell脚本在执行时会对系统环境产生影响,比如生成或移动文件等,如果在实际执行才发现语法错误,您不得不手工做一些系统环境的恢复工作才能继续测试这个脚本。

    "-c"选项使shell解释器从一个字符串中而不是从一个文件中读取并执行shell命令。当需要临时测试一小段脚本的执行结果时,可以使用这个选项,如下所示:
    sh -c 'a=1;b=2;let c=$a+$b;echo "c=$c"'

    "-x"选项可用来跟踪脚本的执行,是调试shell脚本的强有力工具。"-x"选项使shell在执行脚本的过程中把它实际执行的每一个命令行显示出来,并且在行首显示一个"+"号。 "+"号后面显示的是经过了变量替换之后的命令行的内容,有助于分析实际执行的是什么命令。 "-x"选项使用起来简单方便,可以轻松对付大多数的shell调试任务,应把其当作首选的调试手段。


    如果把本文前面所述的trap ‘command’ DEBUG机制与“-x”选项结合起来,我们就可以既输出实际执行的每一条命令,又逐行跟踪相关变量的值,对调试相当有帮助。

    我们以debug.sh脚本为例:

    # cat -n debug.sh  

         1	#!/bin/sh
         2	trap 'echo "before execute line:$LINENO,a=$a,b=$b,c=$c"' DEBUG
         3	a=1
         4	if [ "$a" -eq 1 ]
         5	then 
         6		b=2
         7	else 
         8		b=1
         9	fi
        10	c=3
        11	echo end
    

    现在对该脚本加上“-x”选项来执行它:

    当第2行被注释掉 当第2行没有被注释掉(即代码中有trap命令)

    在上面的结果中,前面有“+”号的行是shell脚本实际执行的命令,前面有“++”号的行是执行trap机制中指定的命令,其它的行则是输出信息。

    shell的执行选项除了可以在启动shell时指定外,亦可在脚本中用set命令来指定。 "set - 参数"表示启用某选项,"set +参数"表示关闭某选项。有时候我们并不需要在启动时用"-x"选项来跟踪所有的命令行,这时我们可以在脚本中使用set命令,如以下脚本片段所示:

    set -x#启动"-x"选项
    要跟踪的程序段
    set +x#关闭"-x"选项

    set命令同样可以使用前面介绍的调试钩子—DEBUG函数来调用,下面是DEBUG函数代码:
    #cat –n debugOth.sh 

    #!/bin/sh
    DEBUG()
    {
    	if [ "DEBUG"="true" ];then
    		$@
    	fi
    }
    a=1
    DEBUG echo "a=$a"
    if [ "$a" -eq 1 ]
    then 
    	b=2
    else 
    	b=1
    fi
    DEBUG echo "b=$b"
    c=3
    DEBUG echo "c=$c"
    $@与$*相同,但是使用时加引号,并在引号中返回每个参数。
    如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
    这样可以避免脚本交付使用时删除这些调试语句的麻烦,如以下脚本片段所示:

    DEBUG set -x#启动"-x"选项
    要跟踪的程序段

    DEBUG set +x#关闭"-x"选项

    # sh debugOth.sh# sh -x debugOth.sh

    . "-x"选项的增强

    "-x"执行选项是目前最常用的跟踪和调试shell脚本的手段,但其输出的调试信息仅限于进行变量替换之后的每一条实际执行的命令以及行首的一个"+" 号提示符,居然连行号这样的重要信息都没有,对于复杂的shell脚本的调试来说,还是非常的不方便。幸运的是,我们可以巧妙地利用shell内置的一些环境变量来增强"-x"选项的输出信息,下面先介绍几个shell内置的环境变量:

    $LINENO
    代表shell脚本的当前行号,类似于C语言中的内置宏__LINE__

    $FUNCNAME
    函数的名字,类似于C语言中的内置宏__func__,但宏__func__只能代表当前所在的函数名,而$ FUNCNAME的功能更强大,它是一个数组变量,其中包含了整个调用链上所有的函数的名字,故变量${FUNCNAME[0]}代表shell脚本当前正在执行的函数的名字,而变量${FUNCNAME[1]}则代表调用函数${FUNCNAME[0]}的函数的名字,余者可以依此类推。

    $PS4
    主提示符变量$PS1和第二级提示符变量$PS2比较常见,但很少有人注意到第四级提示符变量$PS4的作用。我们知道使用“- x”执行选项将会显示shell脚本中每一条实际执行过的命令,而$PS4的值将被显示在“-x”选项输出的每一条命令的前面。在Bash Shell中,缺省的$PS4的值是"+"号。(现在知道为什么使用"-x"选项时,输出的命令前面有一个"+"号了吧?)

    利用$PS4这一特性,通过使用一些内置变量来重定义$PS4的值,我们就可以增强"-x"选项的输出信息。例如先执行export PS4='+{$LINENO:${FUNCNAME[0]}} ', 然后再使用“-x”选项来执行脚本,就能在每一条实际执行的命令前面显示其行号以及所属的函数名。

    以下是一个存在bugshell脚本的示例,本文将用此脚本来示范如何用“-n”以及增强的“-x”执行选项来调试shell脚本。这个脚本中定义了一个函数isRoot(),用于判断当前用户是不是root用户,如果不是,则中止脚本的执行。

    # cat -n debugOthO.sh

         1	#!/bin/sh
         2	isRoot()
         3	{
         4	if [ "$UID" -ne 0 ]
         5		return 1
         6	else
         7		return 0
         8	fi
         9	}
        10	isRoot
        11	if ["$?" -ne 0]
        12	then
        13		echo "Must be root to run this script"
        14		exit 1
        15	else
        16		echo "welcome root user"
        17		#do something
        18	fi
    

    首先执行# sh -n debugOthO.sh来进行语法检查,输出如下:
    # sh -n debugOthO.sh
    exp4.sh: line 6: syntax error near unexpected token `else'
    exp4.sh: line 6: ` else'

    发现了一个语法错误,通过仔细检查第6行前后的命令,我们发现是第4行的if语句缺少then关键字引起的(写惯了C程序的人很容易犯这个错误)。我们可以把第4行修改为if [ "$UID" -ne 0 ]; then来修正这个错误。再次运行# sh -n debugOthO.sh来进行语法检查,没有再报告错误。接下来就可以实际执行这个脚本了,执行结果如下:

    # sh -n debugOthO.sh
    exp2.sh: line 11: [1: command not found
    welcome root user

    尽管脚本没有语法错误了,在执行时却又报告了错误。错误信息还非常奇怪“[1: command not found”。现在我们可以试试定制$PS4的值,并使用“-x”选项来跟踪:

    $ export PS4='+{$LINENO:${FUNCNAME[0]}} '
    $ sh –x debugOthO.sh

    +{10:} isRoot
    +{4:isRoot} '[' 503 -ne 0 ']'
    +{5:isRoot} return 1
    +{11:} '[1' -ne 0 ']'
    exp4.sh: line 11: [1: command not found
    +{16:} echo 'welcome root user'
    welcome root user

    从输出结果中,我们可以看到脚本实际被执行的语句,该语句的行号以及所属的函数名也被打印出来,从中可以清楚的分析出脚本的执行轨迹以及所调用的函数的内部执行情况。由于执行时是第11行报错,这是一个if语句,我们对比分析一下同为if语句的第4行的跟踪结果:

    +{4:isRoot} '[' 503 -ne 0 ']'
    +{11:} '[1' -ne 0 ']'

    到这里我们就知道由于第11行的[号后面缺少了一个空格,导致[号与紧挨它的变量$?的值1shell解释器看作了一个整体,并试着把这个整体视为一个命令来执行,故有“[1: command not found”这样的错误提示。只需在[号后面插入一个空格就一切正常了。

    shell中还有其它一些对调试有帮助的内置变量,比如在Bash Shell中还有BASH_SOURCE, BASH_SUBSHELL等一批对调试有帮助的内置变量,您可以通过man shman bash来查看,然后根据您的调试目的,使用这些内置变量来定制$PS4,从而达到增强“-x”选项的输出信息的目的。

    . 总结

    现在让我们来总结一下调试shell脚本的过程:
    首先使用“-n”选项检查语法错误,然后使用“-x”选项跟踪脚本的执行,使用“-x”选项之前,别忘了先定制PS4变量的值来增强“-x”选项的输出信息,至少应该令其输出行号信息(先执行export PS4='+[$LINENO]',更一劳永逸的办法是将这条语句加到您用户主目录的.bash_profile文件中去),这将使你的调试之旅更轻松。也可以利用trap,调试钩子等手段输出关键调试信息,快速缩小排查错误的范围,并在脚本中使用“set -x”“set +x”对某些代码块进行重点跟踪。这样多种手段齐下,相信您已经可以比较轻松地抓出您的shell脚本中的臭虫了。
    如果您的脚本足够复杂,还需要更强的调试能力,可以使用shell调试器bashdb,这是一个类似于GDB的调试工具,可以完成对shell脚本的断点设置,单步执行,变量观察等许多功能,使用bashdb对阅读和理解复杂的shell脚本也会大有裨益。关于bashdb安装和使用,不属于本文范围,您可参阅http://bashdb.sourceforge.net/上的文档并下载试用


    参考链接:

    http://www.360doc.com/content/17/0706/19/33093582_669392362.shtml



    展开全文
  • 原文:... if [ str1 = str2 ] 当两个串有相同内容、长度时为真  if [ str1 != str2 ] 当串str1和str2不等时为真  if [ -n str1 ] 当串的长度大于0时为真(串非空)  if [ -z str1 ] 当串的...

    原文:https://www.cnblogs.com/ariclee/p/6137456.html

    if [ str1 = str2 ]       当两个串有相同内容、长度时为真 
    if [ str1 != str2 ]      当串str1和str2不等时为真 
    if [ -n str1 ]       当串的长度大于0时为真(串非空) 
    if [ -z str1 ]        当串的长度为0时为真(空串) 
    if [ str1 ]         当串str1为非空时为真

    shell 中利用 -n 来判定字符串非空。

    错误用法:

    ARGS=$*

    if [ -n $ARGS  ]

    then

       print "with argument"

    fi

    print " without argument"

    不管传不传参数,总会进入if里面。

    原因:因为不加“”时该if语句等效于if [ -n ],shell 会把它当成if [ str1 ]来处理,-n自然不为空,所以为正。

     

    正确用法:需要在$ARGS上加入双引号,即"$ARGS".

     

    ARGS=$*

    if [ -n "$ARGS"  ]

    then

       print "with argument"

    fi

    print " without argument"

    展开全文
  • 在写脚本的时候,总是搞不... zero = 0- 变量的值,为空,返回0,为true- 变量的值,非空,返回1,为false-n 判断变量的值,是否为空 name = 名字- 变量的值,为空,返回1,为false- 变量的值,非空,返回0,为true...

    在写脚本的时候,总是搞不懂[] [[]]的区别,这次写一个总结,把它掌握牢固

    应用场景分析:

    1、在中括号中,判断变量的值, 加不加双引号的问题?

    -z 判断 变量的值,是否为空; zero = 0

    - 变量的值,为空,返回0,为true
    - 变量的值,非空,返回1,为false
    -n 判断变量的值,是否为空 name = 名字
    - 变量的值,为空,返回1,为false
    - 变量的值,非空,返回0,为true
    pid="123"
    [ -z "$pid" ] 单对中括号变量必须要加双引号
    [[ -z $pid ]] 双对括号,变量不用加双引号

    [ -n "$pid" ] 单对中括号,变量必须要加双引号
    [[ -z $pid ]] 双对中括号,变量不用加双引号

    2、多个条件判断,[] 和 [[]] 的区别?
    2.1:[[ ]] 双对中括号,是不能使用 -a 或者 -o的参数进行比较的;
    && 并且 || 或 -a 并且 -o 或者
    [[ ]] 条件判断 && 并且 || 或

    [[ 5 -lt 3 || 3 -gt 6 ]] 一个条件,满足,就成立 或者的关系
    [[ 5 -lt 3 || 3 -gt 6 ]] 一个条件满足,就成立 或者的关系

    [[ 5 -lt 3 ]] || [[3 -gt 6 ]]
    [[ 5 -lt 3 ]] || [[3 -gt 6 ]] 写在外面也可以


    && 必须两个条件同时满足,和上述一样,这里想说明的问题的是:

    [[ 5 -lt 3]] -o [[ 3 -gt 6 ]] [[ 5 -lt 3 -o 3 -gt 6 ]]
    [[ 5 -lt 3 -a 3 -gt 6 ]] [[ 5 -lt 3 -a 3 -gt 6 ]]
    -a 和 -o就不成立了,是因为,[[]] 双对中括号,不能使用 -o和 -a的参数
    直接报错:

    2.2 [ ] 可以使用 -a -o的参数,但是必须在 [ ] 中括号内,判断条件,例如:
    [ 5 -lt 3 -o 3 -gt 2 ] 或者条件成立
    [5 -lt 3 ] -o [ 3 -gt 2] 或者条件, 这个不成立,因为必须在中括号内判断

    如果想在中括号外判断两个条件,必须用&& 和 || 比较
    [5 -lt 3 ] || [ 3 -gt 2]
    [5 -gt 3 ] && [ 3 -gt 2] 成立

    相对的,|| 和 && 不能在中括号内使用,只能在中括号外使用
    3、当判断某个变量的值是否满足正则表达式的时候,必须使用[[ ]] 双对中括号

    单对中括号,直接报错:


    展开全文
  • O-Linux&Shell-W3

    2020-03-11 21:31:55
    Shell-W3 Linux系统管理(共10分) 一、操作题(每题1分,共10分) 1、 新建一个用户sam,将用户的主目录设置到 /usr/sam目录。 2、 新建一个用户gem,将用户的登录Shell设置为/bin/sh,用户组(源生组)设置为group...

    O-Linux&Shell-W3

    Linux系统管理(共10分)

    一、操作题(每题1分,共10分)

    1、 新建一个用户sam,将用户的主目录设置到 /usr/sam目录。

    2、 新建一个用户gem,将用户的登录Shell设置为/bin/sh,用户组(源生组)设置为group,附加组(衍生组)设置为adm和root。

    3、 调整sam用户,主目录改为/home/z,用户组改为developer。

    4、 设置sam用户的密码。

    5、 删除sam用户。

    6、 新建group1组。

    7、 新建group2组并将组标识号设定为101.

    8、 删除group1组。

    9、 调整group2组的组标识号为102。

    10、将group2的组名改为group3。

    解析步骤

    1.建议用root用户登陆

    useradd -d /usr/sam -m sam
    

    其中 useradd [username] 是用来添加用户的命令, -d 是用来指定路径目录,由于我们的系统原来并没有 /usr/sam 这个目录,所以用 -m 命令来新建这个目录。
    在这里插入图片描述
    2.

    groupadd group 
    #groupadd adm 这一段注释的代码是新建adm组,
    #一般我们的系统中没有 group组,但是默认有 adm组,所以只建group即可
    useradd -s /bin/sh -g group -G adm,root gem
    

    groupadd [groupname] 是用来添加组的命令,-s 是用来指定这个新用户登陆的Shell目录,-g 是指定用户组(源生组)-G 是指定用户的附加组(衍生组)多个附加组用, 隔开,最后便是新建用户的用户名。
    在这里插入图片描述
    在这里插入图片描述
    3.

    groupadd developer
    #此处也是,我们的系统中并无 developer 组,所以要新建
    usermod -d home/z -g developer sam
    

    usermod 是用来更改用户信息的命令,-d-g 的作用上文已提及,此处不再赘述。
    在这里插入图片描述
    4.

    passwd sam
    

    passwd [username] 是在root用户下用来给任何用户更改密码的命令(如果在普通用户下更改所在用户的密码,直接键入passwd 回车 即可出现提示)。
    P.S.如果你输入的密码过短,系统会提示你,但是你可以忽略。
    在这里插入图片描述
    5.

    userdel sam
    

    userdel [username] 是用来删除用户的命令。(在本操作中,由于我们不仅建立了sam用户,还建立了sam组,单独的userdel命令只能删除用户,sam组依然存在)。
    在这里插入图片描述
    6.

    groupadd group1
    groupadd -g 101 group2
    #在此处 groupadd后的 -g 作用是来指定组的识别号,可理解为group_id
    groupdel group1
    groupmod -g 102 group2
    groupmod -n group3 group2
    # -n的作用是用来修改name组名,可理解为一个方法 -n new_name old_name 就是将old_name 更改为 new_name
    

    此处需要解释的是 groupmod命令,这是用来修改组信息的命令。
    在这里插入图片描述

    最后,这篇博客有助于你更加深刻的了解:
    https://www.cnblogs.com/monogem/p/9802593.html

    展开全文
  • 原帖: ... shell下的read命令的作用是从标准流中读取输入,并把读取的内容放到某个变量中。 用法:read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t

    原帖: http://blog.csdn.net/misskissc/article/details/8154051


    shell下的read命令的作用是从标准流中读取输入,并把读取的内容放到某个变量中。

    用法:read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]

    今天此篇记录read命令的 -t 、-n、 -s三大参数:

     

    -t】参数

    -t参数给用户的输入做限时规定。若超出-t参数后所规定的时间值后,脚本将终止用户的输入,可单独使用也可和其它参数配合连用。

    read_t.sh

    图1.-t 设定交互界面时间参数

    若在-t参数后3(以秒为单位)秒后完成输入(完成输入且键入回车),则相应的shell变量将会获得对应的值。否则shell变量的值为空。

     

    -n】参数

    参数-n规定read后面的变量所接收的字符个数。只要在shell界面输入到-n所规定的字符数之后,shell变量立即被赋值。若是没有得到所规定的字符数,shell界面给予等待。

    例read_n.sh

    图2.-n规定shell变量所接收的shell界面输入字符数

     

    [3]语句除了在20s后会自动运行到第5行外,若用户在shell界面输入10个字符后,name变量立马拥有shell界面输入的字符串值,并执行到第5行。

     

    -s】参数

    有时会需要脚本用户输入,但不希望输入的数据显示在监视器上。如用户密码等。

    -s选项能够使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是read命令将文本颜色设置成与背景相同的颜色)。

    例read_s.sh

    图3.-s屏蔽read读参数时的字符回显

    第5行是作换行处理。第六行是将name接收到的参数输出来瞧瞧。

    如运行脚本后输入:sh

    得到输出界面为:

    图4.read_s.sh运行结果

    图四中划红线上面就是输入参数的位置,可见加入参数-s后,成功屏蔽字符回显。


    展开全文
  • echo -n 不换行输出$echo -n "123" $echo "456"12最终输出 123456 而不是 123 456123456echo -e 处理特殊字符若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出: \a ...
  • 在学习shell脚本时发现在做if判断时,对于空字符串的判断上-n做出了一些错误的判定
  • shell下的read命令的作用是从标准流中读取输入,并把读取的内容放到某个变量中。 用法:read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...] 今天...
  • shell中sed命令-N选项的理解最近用到shell中的sed命令,当时对于-N选项的用法很疑惑,后经过思索终于弄明白了,写在这里记录一下。
  • Shell的判断条件有两种写法:1.-lt(小于),-gt(大于),-le(小于等于),-ge(大于等于),-eq(等于),-ne(不等于) l--less g--great t--than e--equal n--not if [ $s -lt 0 ] || [ $s -gt 100 ] then echo "...
  • 本文介绍if语法使用方法、特殊文本表达式-z -n -f -eq -ne -lt等及shell的逻辑表达式用法。 1.if语法 条件表达式一定要有fi结尾!!! if语法格式 命令执行成功,返回0 (比如grep ,找到匹配) 执行失败,返回非0...
  • shell下的read命令的作用是从标准流中读取输入,并把读取的内容放到某个变量中。 用法:read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...] 今天此...
  • shell下的read命令的作用是从标准流中读取输入,并把读取的内容放到某个变量中。 用法:read [-ers] [-a array] [-ddelim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name...] 此篇...
  • linux命令学习(7)—— watch -nwatch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行。在Linux下,watch是周期性的执行...
  • #其他参数还有-n,-n是判断一个变量是否是否有值 if [ ! -n "$myVar" ]; then echo "$myVar is empty" exit 0 fi  沃建设#each_day_file_processed_number /home/unicomlabs/*_bak5/log/log_*  for ...
  • [ str ] //str 字符串存在为真 示例: [root@localhost ~]# if [ ]; then echo 'true';else echo 'false';fi false [root@localhost ~]# [root@localhost ~]# if [ 123 ]; then echo 'true';...
  • 在Unix Shell中,可以使用[ -n ]来判断一个string不是NULL值,但是之前却以为这是骗人的把戏。因为执行下面的命令,返回是0值(即真),可是BB明明是没有内容的。 [root]# export BB= [root]# [ -n $BB ] ...
1 2 3 4 5 ... 20
收藏数 252,987
精华内容 101,194
热门标签
关键字:

-n linux shell