我正在编写一个 bash 脚本,我想为多种类型的 VCS 工作。我正在考虑通过运行典型的 info 命令并检查返回码、成功或错误来测试目录是否是系统的存储库。在伪代码中:
if a svn command succeded;
Then run svn commands
elif a darcs command succeded;
Then run darcs commands
elif a mercurial command succeded;
then run hg commands
else
something else
fi
Run Code Online (Sandbox Code Playgroud)
我可以运行一个命令,例如
darcs show repo并使用它$?来获取它的返回码。
我的问题是:有没有一种简洁的方法可以在一行中运行并返回返回代码号?例如
if [ 0 -eq `darcs show repo`$? ];
Run Code Online (Sandbox Code Playgroud)
还是我必须定义一个函数?
一个额外的要求是 stderr 和 stdout 都应该被打印出来。
我想要以下命令结构:
command && check-status | less && followup-command
Run Code Online (Sandbox Code Playgroud)
这将在用户与 交互时暂停执行less。用户如何强制less以非零状态退出以防止followup-command运行?
我目前正在使用 less 458 (POSIX regular expressions)
我在脚本下面运行:
#!/bin/bash
ps ax | grep -q [v]arnish
if [ $? -eq 0 ];then
echo varnish is running...
exit 0
else
echo "Critical : varnish is not running "
exit 2
fi
Run Code Online (Sandbox Code Playgroud)
输出就像 ::
[root@server ~]# sh -x check_varnish_pro.sh
+ ps ax
+ grep -q '[v]arnish'
+ '[' 0 -eq 0 ']'
+ echo varnish is running...
varnish is running...
+ exit 0
Run Code Online (Sandbox Code Playgroud)
当我在命令行中运行相同时,我的退出状态为 1:
[root@server ~]# ps ax | grep -q [v]arnish; echo $?
1
Run Code Online (Sandbox Code Playgroud)
这种情况就像服务器中没有安装清漆。此脚本在安装了 varnish 的服务器中运行良好。
为什么使用脚本和命令行运行时退出状态不同?如何改进这个脚本?
请参阅以下示例及其在 POSIX shell 中的输出:
false;echo $?或false || echo 1:1false;foo="bar";echo $?或foo="bar" && echo 0:0foo=$(false);echo $?或foo=$(false) || echo 1:1foo=$(true);echo $?或foo=$(true) && echo 0:0正如/sf/ask/478414121/ 上投票最高的答案所提到的:
$?用于查找上次执行命令的返回值。
在这种情况下,这可能有点误导,所以让我们获取 POSIX 定义,该定义也在该线程的帖子中引用:
? 扩展到最近管道的十进制退出状态(请参阅管道)。
所以看起来好像一个赋值本身算作一个命令(或者更确切地说是一个管道部分),它的退出值为零,但它应用在赋值的右侧之前(例如,我的示例中的命令替换调用)。
从实际的角度来看,我看到这种行为是有道理的,但对我来说,作业本身按该顺序计数似乎有些不寻常。也许为了让我更清楚为什么这对我来说很奇怪,让我们假设赋值是一个函数:
ASSIGNMENT( VARIABLE, VALUE )
Run Code Online (Sandbox Code Playgroud)
那么foo="bar"将是
ASSIGNMENT( "foo", "bar" )
Run Code Online (Sandbox Code Playgroud)
并且foo=$(false)会像
ASSIGNMENT( "foo", EXECUTE( "false" ) )
Run Code Online (Sandbox Code Playgroud)
这意味着首先EXECUTE …
使用
time sleep 1
Run Code Online (Sandbox Code Playgroud)
产量:
$ time sleep 1
real 0m1.005s
user 0m0.001s
sys 0m0.001s
Run Code Online (Sandbox Code Playgroud)
有没有我可以用来打印退出代码sleep或我想运行的任何命令的命令?
喜欢的东西:
$ log-exit-code sleep 1
Run Code Online (Sandbox Code Playgroud)
也许这足够了?
sleep 1 && echo "$?"
Run Code Online (Sandbox Code Playgroud) $ echo "$?"
0
$ echo 'q' | dc || echo "$?"
1
Run Code Online (Sandbox Code Playgroud)
为什么使用q退出dc被认为是错误?
(测试在Ubuntu 20.4上运行。)
我在 bash 脚本中有这个:
exit 3;
exit_code="$?"
if [[ "$exit_code" != "0" ]]; then
echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
exit "$exit_code";
fi
Run Code Online (Sandbox Code Playgroud)
看起来它会在退出命令后立即退出,这是有道理的。我想知道是否有一些简单的命令可以提供退出代码而无需立即退出?
我猜:
exec exit 3
Run Code Online (Sandbox Code Playgroud)
但它给出了一条错误消息:exec: exit: not found。我能做什么?:)
考虑这个脚本:
#!/bin/sh
foo=1
if [[ ! -z $foo ]]; then
echo abc
fi
Run Code Online (Sandbox Code Playgroud)
它使用 Bash 语法 [[ ... ]] 当我在 Ubuntu (dash) 上使用默认 shell 运行它时,它不起作用(如预期)。但是,它的返回码仍然为零。
$ ./tmp.sh
./tmp.sh: 4: ./tmp.sh: [[: not found
$ echo $?
0
Run Code Online (Sandbox Code Playgroud)
如果我不能依赖退出代码,如何在脚本中检测这种错误?
如何提取命令的退出代码并在条件中使用它?例如看下面的脚本:
i=4
if [[ $i -eq 4 && $(command) -eq 0 ]]
then
echo "OK"
else
echo "KO"
fi
Run Code Online (Sandbox Code Playgroud)
如果这两个条件都满足,脚本应该做一些事情。在第二种情况下,我需要检查退出状态(而不是上面给出的脚本中的命令输出),以了解命令是否成功。
exit-status ×10
bash ×4
shell-script ×3
exit ×2
shell ×2
assignment ×1
dash ×1
dc ×1
exec ×1
less ×1
math ×1
posix ×1
process ×1
ps ×1