所以我喜欢尽可能地强化我的 bash 脚本(并且当不能委托给像 Python/Ruby 这样的语言时)以确保错误不会被发现。
在这种情况下,我有一个 strict.sh,其中包含以下内容:
set -e
set -u
set -o pipefail
Run Code Online (Sandbox Code Playgroud)
并在其他脚本中获取它。然而,虽然 pipefail 会出现:
false | echo it kept going | true
它不会拿起:
echo The output is '`false; echo something else`'
Run Code Online (Sandbox Code Playgroud)
输出将是
输出是''
False 返回非零状态和非标准输出。在管道中它会失败,但在这里没有发现错误。当这实际上是存储在变量中的计算供以后使用,并且该值设置为空白时,这可能会导致以后出现问题。
那么 - 有没有办法让 bash 将反引号内的非零返回码视为足以退出的理由?
我有一个下一个格式的字符串
id;some text here with possible ; inside
Run Code Online (Sandbox Code Playgroud)
并希望通过第一次出现 将其拆分为 2 个字符串;。所以,它应该是:id和some text here with possible ; inside
我知道如何拆分字符串(例如,使用cut -d ';' -f1),但由于我;在左侧部分,因此它将拆分为更多部分。
我想做这样的事情:
if cmd1 && cmd2
echo success
else
echo epic fail
fi
Run Code Online (Sandbox Code Playgroud)
我该怎么做?
我需要连接两个变量来创建一个带有下划线的文件名。让我们调用我的变量$FILENAME以及$EXTENSION从文件中读取文件名的位置。
FILENAME=Hello
EXTENSION=WORLD.txt
Run Code Online (Sandbox Code Playgroud)
现在...
我尝试了以下但没有成功:
NAME=${FILENAME}_$EXTENSION
NAME=${FILENAME}'_'$EXTENSION
NAME=$FILENAME\\_$EXTENSION
Run Code Online (Sandbox Code Playgroud)
我总是得到某种奇怪的输出。通常下划线在前。
我需要它
echo $NAME
Hello_WORLD.txt
Run Code Online (Sandbox Code Playgroud) 有时您必须确保同一时间只有一个 shell 脚本实例正在运行。
例如,通过 crond 执行的 cron 作业本身不提供锁定(例如默认的 Solaris crond)。
实现锁定的常见模式是这样的代码:
#!/bin/sh
LOCK=/var/tmp/mylock
if [ -f $LOCK ]; then # 'test' -> race begin
echo Job is already running\!
exit 6
fi
touch $LOCK # 'set' -> race end
# do some work
rm $LOCK
Run Code Online (Sandbox Code Playgroud)
当然,这样的代码有竞争条件。有一个时间窗口,其中两个实例的执行都可以在第 3 行之后才能访问$LOCK文件。
对于 cron 作业,这通常不是问题,因为两次调用之间有几分钟的间隔。
但是事情可能会出错——例如,当锁定文件在 NFS 服务器上时——挂起。在这种情况下,多个 cron 作业可以在第 3 行阻塞并排队。如果NFS服务器再次处于活动状态,那么你已经惊群并行运行的作业。
在网上搜索我发现工具lockrun似乎是该问题的一个很好的解决方案。使用它,您可以运行一个需要像这样锁定的脚本:
$ lockrun --lockfile=/var/tmp/mylock myscript.sh
Run Code Online (Sandbox Code Playgroud)
您可以将其放在包装器中或从您的 crontab 中使用它。
lockf()如果可用,它使用(POSIX) 并回退到flock()(BSD)。并且lockf()对 NFS …
我有一个实用程序,由几个目录组成,其中包含一些 bash 脚本和支持文件,这些文件将部署到多台机器上,可能在每台机器上的不同目录中。脚本需要能够引用相对于自身的路径,因此我需要能够获取当前正在执行的文件的路径。
我知道dirname $0直接调用我的脚本时可以完美运行的习语。不幸的是,人们希望能够从完全不同的目录创建指向这些脚本的符号链接,并且仍然具有相对路径逻辑的工作。
整体目录结构示例如下:
/
|-usr/local/lib
| |-foo
| | |-bin
| | | |-script.sh
| | |-res
| | | |-resource_file.txt
|-home/mike/bin
| |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)
Run Code Online (Sandbox Code Playgroud)
我怎样才能可靠地引用/usr/local/lib/foo/res/resource_file.txt来自script.sh它是否被调用/usr/local/lib/foo/bin/script.sh或~mike/bin/link_to_script?
我试图了解这个Docker 入口点的作用。
在我看来,这是编写 Dockerfile 时非常常见的模式,但我的 bash 技能有限,而且我不知道所有特殊的 bash 符号功夫。
此外,很难用谷歌搜索“--”、“$!” 等等。这些在 bash 世界中被称为什么?
总而言之,下面的行试图做什么?
if [ "${1#-}" != "$1" ]; then
set -- haproxy "$@"
fi
Run Code Online (Sandbox Code Playgroud) 我正在创建一个 shell 脚本,它将获取文件的文件名/路径并确定该文件是符号链接还是硬链接。
唯一的问题是,我不知道如何查看它们是否是硬链接。我创建了 2 个文件,一个是硬链接,一个是符号链接,用作测试文件。但是我如何确定一个文件是一个硬链接还是一个 shell 脚本中的符号?
另外,我如何找到符号链接的目标分区?因此,假设我有一个链接到不同分区的文件,我如何找到该原始文件的路径?
在 bash 脚本中:
我们通过命名来创建变量:
abc=ok
Run Code Online (Sandbox Code Playgroud)
或者我们可以使用 declare
declare abc=ok
Run Code Online (Sandbox Code Playgroud)
有什么不同?
为什么 bash 有这么多方法来创建变量?