“&& vs if [ $? -ne 0 ] vs set -e”管理子进程

“&& vs if [ $? -ne 0 ] vs set -e”管理子进程

我制作了一个主 shell,一次调用多个步骤 shell

#!/bin/bash
##I'm the master shell and I'm super important. I should never fail to log.

bash ./step1.sh
bash ./step2.sh
bash ./step3.sh
bash ./step4.sh

...

在调用后一个 shell 之前,步骤 shell 不得失败。
我正在考虑 3 种方法来做到这一点,但实际上我不知道它们到底是做什么的。

方法1)

bash ./step1.sh &&
bash ./step2.sh &&
bash ./step3.sh &&
bash ./step4.sh &&
...

方法2)

bash ./step1.sh 

if [ $? -eq 0 ]; then
  bash ./step2.sh 
fi

if [ $? -eq 0 ]; then
  bash ./step3.sh
fi

if [ $? -eq 0 ]; then
    bash ./step4.sh
fi
...

方法3)

set -e
bash ./step1.sh
bash ./step2.sh
bash ./step3.sh
bash ./step4.sh
...
set +e

我需要主脚本在其中一个脚本失败时立即终止step,并且我需要能够记录失败的步骤。

哪一种是最优选的,哪一种是最安全的?

答案1

撇开“最安全”不谈,因为你从来没有说过什么行为是“安全”的,而“首选”是不知道你的脚本在做什么,很可能有“更好”的方法来实现你想要做的事情。

由于您需要在退出主脚本之前在单个步骤之一中记录失败,因此您无法真正运行这些步骤之下set -e或之间的链中的步骤&&。也就是说,除非step脚本本身记录失败。

假设主脚本需要记录故障: 主脚本需要能够运行下一个脚本并检测故障。然后,它需要在终止之前通知用户此失败。

我可能会选择第二种方法的变体:

#!/bin/bash

for step in {1..4}; do
    if ! bash "./step$step.sh"; then
        printf 'Step %s failed, terminating...\n' "$step" >&2
        exit 1
    fi
done

echo 'All done, no failures'

此循环遍历整数 1 到 4,并在每次迭代中执行适当的脚本。如果脚本失败,它会向用户记录一条诊断消息,并以非零退出状态终止。

您显然可以使用而不是循环整数

#!/bin/sh

for script in ./step*.sh; do
    if ! bash "$script"; then
        printf 'Script "%s" failed, terminating...\n' "$script" >&2
        exit 1
    fi
done

echo 'All done, no failures'

...这将循环实际的步骤脚本(按照文件名通配返回它们的顺序),或者

#!/bin/bash

for script in ./step{1..4}.sh; do
    if ! bash "$script"; then
        printf 'Script "%s" failed, terminating...\n' "$script" >&2
        exit 1
    fi
done

echo 'All done, no failures'

更好地控制脚本的确切顺序(特别是如果您有超过 9 个脚本)。

相关内容