【问题标题】:How to start a shell script from a specific line?如何从特定行启动 shell 脚本?
【发布时间】:2015-06-14 21:42:28
【问题描述】:
#!/bin/sh
echo "install 1"
echo "install 2"
[ $? -eq 0 ] || exit $?;
cyberciti 
[ $? -eq 0 ] || exit $?;
echo "install 3"
echo "install 4"

上述脚本在第 4 行 (cyberciti) 失败。如何获取行号,并从该行开始重新运行脚本,在进行所需的更正后,跳过已执行的命令?

【问题讨论】:

    标签: linux shell


    【解决方案1】:

    当你认为你经常需要做这样的事情时,你可以使用一个特殊的变量。并制作一个可选的命令行参数(默认从开头开始)告诉您从哪里开始。
    非结构化版本如下所示:

    #!/bin/sh
    if [ $# -eq 1 ]; then
       PHASE=$1
    else
       PHASE=1
    fi
    echo phase $PHASE
    
    if [ ${PHASE} -eq 1 ]; then
            echo "install 1"
            (( PHASE = PHASE + 1 ))
    fi
    
    if [ ${PHASE} -eq 2 ]; then
            echo "install 2"
            [ $? -eq 0 ] || exit $?;
            (( PHASE = PHASE + 1 ))
    fi
    
    if [ ${PHASE} -eq 3 ]; then
            echo cyberciti
    [ $? -eq 0 ] || exit $?;
            # Still phase 3, cyberciti is not a special phase
    
            echo "install 3"
            (( PHASE = PHASE + 1 ))
    fi
    
    if [ ${PHASE} -eq 4 ]; then
            echo "install 4"
            (( PHASE = PHASE + 1 ))
    fi
    

    一个改进是使用一个while循环:

    #!/bin/sh
    if [ $# -eq 1 ]; then
       PHASE=$1
    else
       PHASE=1
    fi
    
    function phase2 {
            echo "install 2"
            [ $? -eq 0 ] || exit $?;
    }
    
    function phase3 {
            echo cyberciti
            [ $? -eq 0 ] || exit $?;
            # Still phase 3, cyberciti is not a special phase
            echo "install 3"
    }
    
    while [ ${PHASE} -lt 5 ]; do
            [ ${PHASE} -eq 1 ] && echo "install 1"
            [ ${PHASE} -eq 2 ] && phase2
            [ ${PHASE} -eq 3 ] && phase3
            [ ${PHASE} -eq 4 ] && echo "install 4"
            (( PHASE = PHASE + 1 ))
    done
    

    进一步的改进可能包括逻辑名称和一些可以在一个阶段内更改的特殊流控制。

    编辑:使用案例构造进行改进

    #!/bin/sh
    if [ $# -eq 1 ]; then
       PHASE=$1
    else
       PHASE=1
    fi
    
    function phase2 {
            echo "install 2"
            [ $? -eq 0 ] || exit $?;
    }
    
    function phase3 {
            echo cyberciti
            [ $? -eq 0 ] || exit $?;
            # Still phase 3, cyberciti is not a special phase
            echo "install 3"
    }
    
    endloop=false
    while [ ${endloop} = false ]; do
       case ${PHASE} in
           1) echo "install 1" ;;
           2) phase2 ;;
           3) phase3 ;;
           4) echo "install 4" ;;
           5) endloop=true ;;
           *) echo "Phase ${PHASE} not supported" ;;
        esac
        (( PHASE = PHASE + 1 ))
    done
    

    【讨论】:

      【解决方案2】:
      #!/bin/sh
      if [ $# -eq 1 ]; then
       PHASE=$1
      else
       PHASE=1
      fi
      if [ ${PHASE} -le 6 ]; then
          echo "install 1 "
          echo "install 2 "
      fi
      if [ ${PHASE} -le 10 ]; then
        cyberciti
        [ $? -eq 0 ] || exit $?;
        echo "install 3 "
        [ $? -eq 0 ] || exit $?;
      fi
      if [ ${PHASE} -le 16 ]; then
          echo "install 4"
          [ $? -eq 0 ] || exit $?;
      fi
      

      这是我需要的最后一个脚本,当我们第一次运行时 (sh test.sh) 将在cyberciti 失败,然后我们只需要在用有效命令替换cyberciti 后从这一行运行,所以它通过新参数作为错误行(sh test.sh 11)从这一行恢复运行

      【讨论】:

        【解决方案3】:

        跳过前 4 行(因此从第 5 行开始):

        tail --lines=+5 script.sh | sh
        

        根据the man page--lines=K表示output the last K lines, instead of the last 10; or use -n +K to output starting with the Kth

        感谢Aaron Digulla 他的回答here。编辑:感谢l0b0 阻止我的cat 来自taking over the world

        【讨论】:

        • UUOC:使用tail --lines=+4 script.sh即可。
        • 谢谢,太好了,想知道是否有一些标志或任何更简单的方法与再次运行脚本没有太大不同,不需要记录长命令,在你的评论中你的意思是 N 行吗?
        • 如果脚本第二次失败,它会返回从 1 开始的行号以及我们正在运行的部分脚本,因此我们需要添加第一个错误行和新的失败行号才能实际恢复从第二次失败
        猜你喜欢
        • 2018-11-03
        • 1970-01-01
        • 2018-10-15
        • 1970-01-01
        • 2011-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多