Get exit code for command in bash/ksh

前端 未结 5 945
死守一世寂寞
死守一世寂寞 2021-02-01 01:08

I want to write code like this:

command=\"some command\"

safeRunCommand $command

safeRunCommand() {
   cmnd=$1

   $($cmnd)

   if [ $? != 0 ]         


        
相关标签:
5条回答
  • 2021-02-01 01:32

    It should be $cmd instead of $($cmd). Works fine with that on my box.

    Edit: Your script works only for one-word commands, like ls. It will not work for "ls cpp". For this to work, replace cmd="$1"; $cmd with "$@". And, do not run your script as command="some cmd"; safeRun command, run it as safeRun some cmd.

    Also, when you have to debug your bash scripts, execute with '-x' flag. [bash -x s.sh].

    0 讨论(0)
  • 2021-02-01 01:32

    The normal idea would be to run the command and then use $? to get the exit code. However, some times you have multiple cases in which you need to get the exit code. For example, you might need to hide it's output but still return the exit code, or print both the exit code and the output.

    ec() { [[ "$1" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }
    

    This will give you the option to suppress the output of the command you want the exit code for. When the output is suppressed for the command, the exit code will directly be returned by the function.

    I personally like to put this function in my .bashrc file

    Below I demonstrate a few ways in which you can use this:


    # In this example, the output for the command will be
    # normally displayed, and the exit code will be stored
    # in the variable $ec.
    
    $ ec echo test
    test
    $ echo $ec
    0
    

    # In this example, the exit code is output
    # and the output of the command passed
    # to the `ec` function is suppressed.
    
    $ echo "Exit Code: $(ec -h echo test)"
    Exit Code: 0
    

    # In this example, the output of the command
    # passed to the `ec` function is suppressed
    # and the exit code is stored in `$ec`
    
    $ ec -h echo test
    $ echo $ec
    0
    

    Solution to your code using this function

    #!/bin/bash
    if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
        echo "Error when executing command: 'grep p' [$ec]"
        exit $ec;
    fi
    

    You should also note that the exit code you will be seeing will be for the grep command that's being run, as it is the last command being executed. Not the ls.

    0 讨论(0)
  • 2021-02-01 01:42

    There are several things wrong with your script.

    Functions (subroutines) should be declared before attempting to call them. You probably want to return() but not exit() from your subroutine to allow the calling block to test the success or failure of a particular command. That aside, you don't capture 'ERROR_CODE' so that is always zero (undefined).

    It's good practice to surround your variable references with curly braces, too. Your code might look like:

    #!/bin/sh
    command="/bin/date -u"          #...Example Only
    
    safeRunCommand() {
       cmnd="$@"                    #...insure whitespace passed and preserved
       $cmnd
       ERROR_CODE=$?                #...so we have it for the command we want
       if [ ${ERROR_CODE} != 0 ]; then
          printf "Error when executing command: '${command}'\n"
          exit ${ERROR_CODE}        #...consider 'return()' here
       fi
    }
    
    safeRunCommand $command
    command="cp"
    safeRunCommand $command
    
    0 讨论(0)
  • 2021-02-01 01:43

    Below is the fixed code:

    #!/bin/ksh
    safeRunCommand() {
      typeset cmnd="$*"
      typeset ret_code
    
      echo cmnd=$cmnd
      eval $cmnd
      ret_code=$?
      if [ $ret_code != 0 ]; then
        printf "Error : [%d] when executing command: '$cmnd'" $ret_code
        exit $ret_code
      fi
    }
    
    command="ls -l | grep p"
    safeRunCommand "$command"
    

    Now if you look into this code few things that I changed are:

    • use of typeset is not necessary but a good practice. It make cmnd and ret_code local to safeRunCommand
    • use of ret_code is not necessary but a good practice to store return code in some variable (and store it ASAP) so that you can use it later like I did in printf "Error : [%d] when executing command: '$command'" $ret_code
    • pass the command with quotes surrounding the command like safeRunCommand "$command". If you dont then cmnd will get only the value ls and not ls -l. And it is even more important if your command contains pipes.
    • you can use typeset cmnd="$*" instead of typeset cmnd="$1" if you want to keep the spaces. You can try with both depending upon how complex is your command argument.
    • eval is used to evaluate so that command containing pipes can work fine

    NOTE: Do remember some commands give 1 as return code even though there is no error like grep. If grep found something it will return 0 else 1.

    I had tested with KSH/BASH. And it worked fine. Let me know if u face issues running this.

    0 讨论(0)
  • 2021-02-01 01:47

    Try

    safeRunCommand() {
       "$@"
    
       if [ $? != 0 ]; then
          printf "Error when executing command: '$1'"
          exit $ERROR_CODE
       fi
    }
    
    0 讨论(0)
提交回复
热议问题