首页 文章

如何执行shell命令?

提问于
浏览
650

在shell脚本中,如何回显所有调用的shell命令并展开任何变量名?例如,给定以下行:

ls $DIRNAME

我希望脚本运行该命令并显示以下内容

ls /full/path/to/some/dir

目的是保存所有调用的shell命令及其参数的日志 . 也许有更好的方法来生成这样的日志?

14 回答

  • 17

    对于 cshtcsh ,您可以 set verboseset echo (或者您甚至可以设置两者,但它可能会在大多数情况下导致一些重复) .

    verbose 选项打印几乎所有您键入的shell表达式 .

    echo 选项更能说明通过产卵将执行的操作 .


    http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose

    http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo


    Special shell variables

    verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

    echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.

  • 2

    我使用函数来回显然后运行命令

    #!/bin/bash
    #function to display commands
    exe() { echo "\$ $@" ; "$@" ; }
    
    exe echo hello world
    

    哪个输出

    $ echo hello world
    hello world
    

    编辑:

    对于更复杂的命令管道等,您可以使用eval:

    #!/bin/bash
    #function to display commands
    exe() { echo "\$ ${@/eval/}" ; "$@" ; }
    
    exe eval "echo 'Hello World' | cut -d ' ' -f1"
    

    哪个输出

    $  echo 'Hello World' | cut -d ' ' -f1
    Hello
    
  • 729

    根据TLDPBash Guide for Beginners: Chapter 2. Writing and debugging scripts

    2.3.1 . 调试整个脚本$ bash -x script1.sh
    ...现在有一个完整的Bash调试器,可以在SourceForge上找到 . 大多数现代版本的Bash都提供这些调试功能,从3.x开始 . 2.3.2 . 调试脚本集的部分-x#从这里激活调试
    w ^
    从这里设置x#停止调试
    ......表2-1 . 设置调试选项概述

    Short  | Long notation | Result  
    -------+---------------+--------------------------------------------------------------
    set -f | set -o noglob | Disable file name generation using metacharacters (globbing).  
    set -v | set -o verbose| Prints shell input lines as they are read.  
    set -x | set -o xtrace | Print command traces before executing command.
    

    ...或者,可以在脚本本身中指定这些模式,方法是在第一行shell声明中添加所需的选项 . 可以组合选项,通常是UNIX命令的情况:#!/ bin / bash -xv

  • 73

    set -xset -o xtrace 展开变量并在该行之前打印一个小符号 .

    set -vset -o verbose 在打印前不会展开变量 .

    使用 set +xset +v 关闭上述设置 .

    在脚本的第一行,可以使 #!/bin/sh -x (或 -v )与脚本中的 set -x (或 -v )具有相同的效果 .

    以上也适用于 /bin/sh .

    http://www.faqs.org/docs/abs/HTML/options.html

    $ cat shl
    #!/bin/bash                                                                     
    
    DIR=/tmp/so
    ls $DIR
    
    $ bash -x shl 
    + DIR=/tmp/so
    + ls /tmp/so
    $
    
  • 65
    $ cat exampleScript.sh
    #!/bin/bash
    name="karthik";
    echo $name;
    
    bash -x exampleScript.sh
    

    输出如下:

    enter image description here

  • 7

    set -x 会给你你想要的 .

    这是一个示例shell脚本来演示:

    #!/bin/bash
    set -x #echo on
    
    ls $PWD
    

    这将扩展所有变量并在输出命令之前打印完整命令 .

    输出:

    + ls /home/user/
    file1.txt file2.txt
    
  • 29

    shuckc回应选择行的答案有一些缺点:你最终还会回复以下 set +x 命令,并且你失去了用 $? 测试退出代码的能力,因为它被 set +x 覆盖了 .

    另一种选择是在子shell中运行命令:

    echo "getting URL..."
    ( set -x ; curl -s --fail $URL -o $OUTFILE )
    
    if [ $? -eq 0 ] ; then
        echo "curl failed"
        exit 1
    fi
    

    这会给你输出像:

    getting URL...
    + curl -s --fail http://example.com/missing -o /tmp/example
    curl failed
    

    但这确实会产生为命令创建新子shell的开销 .

  • 253

    上面发布的人:

    #!/bin/bash
    #function to display commands
    exe() { echo "\$ $@" ; "$@" ; }
    

    这看起来很有希望,但我可以在man bash页面搜索和搜索"$"和"$@",并且一无所获 .

    我知道正在创建一个名为“exec()”的函数 . 我理解花括号标记了函数的开头和结尾 . 我想我明白,分号标志着多行命令之间的“硬回程”,所以'{echo“\ $ $ @”; “$ @”;从本质上说:

    {
    echo "\$ $@"
    "$@"
    
    }
    

    任何人都可以给我一个简短的解释,或者在哪里可以找到这些信息,因为很明显我的google-fu失败了吗?

    (没有意义在旧线程上开始一个新问题,我的目标是将输出重新路由到文件 . “set -x; [commands]; set x”方法对我来说效果很好,但我不能弄清楚如何将结果回显到文件而不是屏幕,所以我试图理解这个其他方法,希望我可以使用非常糟糕的理解重定向/管道/ tee /等来做同样的事情 . )

    谢谢!

    后期编辑:

    通过一些修补,我相信我弄明白了 . 这是我需要的等效代码:

    SCRIPT_LOG="\home\buddy\logfile.txt"
    exe () {
      params="$@"                       # Put all of the command-line into "params"
      printf "%s\t$params" "$(date)" >> "$SCRIPT_LOG"   # Print the command to the log file
      $params                           # Execute the command
    }
    
    exe rm -rf /Library/LaunchAgents/offendingfile
    exe rm -rf /Library/LaunchAgents/secondoffendingfile
    

    logfile.txt中的结果如下所示:

    Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/offendingfile
    Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/secondoffendingfile
    

    正是我需要的 . 谢谢!

  • 1

    另一种选择是将“-x”放在脚本的顶部而不是命令行:

    $ cat ./server
    #!/bin/bash -x
    ssh user@server
    
    $ ./server
    + ssh user@server
    user@server's password: ^C
    $
    

    (对所选答案的评论不足 . )

  • 17

    在bash脚本的名称前面的命令行上键入“bash -x” . 例如,要执行foo.sh,请键入:

    bash -x foo.sh
    
  • 1

    对于zsh echo

    setopt VERBOSE
    

    并用于调试

    setopt XTRACE
    
  • 5

    您还可以通过将它们包装在 set -xset +x 中来为脚本中的选定行切换此选项,例如

    #!/bin/bash
    ...
    if [[ ! -e $OUT_FILE ]];
    then
       echo "grabbing $URL"
       set -x
       curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
       set +x
    fi
    
  • 3

    您可以使用 -x option 在调试模式下使用bash脚本 execute .
    这将回显所有命令 .

    bash -x example_script.sh
    
    # Console output
    + cd /home/user
    + mv text.txt mytext.txt
    

    你也可以 save the -x option in the script . 只需在shebang中指定-x选项即可 .

    ######## example_script.sh ###################
    #!/bin/bash -x
    
    cd /home/user
    mv text.txt mytext.txt
    
    ##############################################
    
    ./example_script.sh
    
    # Console output
    + cd /home/user
    + mv text.txt mytext.txt
    
  • 40

    为了允许回显复合命令,我使用 eval 加上Soth的 exe 函数来回显然后运行命令 . 这对于管道命令很有用,否则它们只会显示无或者只是管道命令的初始部分 .

    没有评估:

    exe() { echo "\$ $@" ; "$@" ; }
    exe ls -F | grep *.txt
    

    输出:

    $
    file.txt
    

    随着eval:

    exe() { echo "\$ $@" ; "$@" ; }
    exe eval 'ls -F | grep *.txt'
    

    哪个输出

    $ exe eval 'ls -F | grep *.txt'
    file.txt
    

相关问题