Ala*_*inD 38 command-line bash scripts
我是 Linux 和 Bash 脚本的新手。在工作中,我看到 Bash 脚本的结构与此类似:
mkdir build && cd build && touch blank.txt
Run Code Online (Sandbox Code Playgroud)
或者:
mkdir build; cd build; touch blank.txt
Run Code Online (Sandbox Code Playgroud)
甚至是异国情调:
COMMAND="mkdir build && cd build && touch blank.txt"
eval ${COMMAND}
Run Code Online (Sandbox Code Playgroud)
最后一个示例给出了一个可能的用例,其中一行可能有用,但通常以下内容更易于阅读并且(至少对我而言)允许您直观地调试脚本:
mkdir build
cd build
touch blank.txt
Run Code Online (Sandbox Code Playgroud)
在一条线上塞满所有东西是否有技术优势?
pa4*_*080 58
mkdir build && cd build && touch blank.txt
Run Code Online (Sandbox Code Playgroud)
在 Bash(和其他一些 shell)中&&是一个逻辑和,这意味着 - 如果前一个命令返回 true,则将执行下一个命令。还有逻辑or ||。例如,您可以将这两个选项组合在一个语句中:
mkdir /tmp/abc/123 && echo 'the dir is created' || echo "the dir isn't created"
Run Code Online (Sandbox Code Playgroud)
注意,构造函数cmd_1 && cmd_2 || comd_3不能代替if; then; else语句,因为无论前面的哪个命令返回false,cmd_3都将被执行。因此,您必须小心使用它的环境。下面是一个例子:
$ true && false || echo success
success
$ false && true || echo success
success
$ false && false || echo success
success
Run Code Online (Sandbox Code Playgroud)
作为经验法则,通常,当我cd在脚本中使用命令时,我会测试目录更改是否成功:cd somewhere/ || exit. 更正确的测试提出@dessert:if ! cd dir; then exit 1; fi。但在所有情况下,为了保护脚本失败,最好使用@mrks' answer 中set -e显示的选项。
mkdir build; cd build; touch blank.txt
Run Code Online (Sandbox Code Playgroud)
; 是一个行分隔符,当在一行中写入很少的分隔命令时使用它。
注意当;或&&与||正在使用它是不是强制性的,在上线写命令-这是中所示@同种的回答。
总的来说,IMO,在一行或单独的行中编写命令之间没有任何特殊的技术优势/区别。
COMMAND="mkdir build && cd build && touch blank.txt"
eval ${COMMAND}
Run Code Online (Sandbox Code Playgroud)
这里一个或多个命令(及其参数)被分组为一个变量的值,然后这个变量(参数)通过eval. 因此,您将能够通过仅在一处更改来更改将在某个脚本中多次执行的命令。
假设您需要更改blank.txt创建文件的方式,例如,您可以通过以下方式更改相关行:
COMMAND="mkdir build && cd build && echo 'test' > blank.txt"
Run Code Online (Sandbox Code Playgroud)
实际eval的优势比的使用alias是当存在重新方向,管道,逻辑运算符等正在使用中。
大多数情况下可以使用functions代替evalwhenalias不适用。此外,如果变量只包含一个命令,即CMD="cat"我们不需要eval,因为 Bash world-split 将"$CMD" "$file1" "$file2"正确扩展。
下面是一个示例,其中eval执行某些命令自动化的最简单方法是:拖尾“在过去一小时内从日志文件中写入的行”是否可能?
在评论中讨论的本节的先前版本可在此处获得。
Bil*_*l K 13
到目前为止的答案解决了会发生什么/它是如何工作的,但我认为你在问“为什么”
这样做(对我而言)而不是在三行中输入它们的主要“原因”是有时命令需要时间(有时是几分钟)并且您不想一直闲逛。
例如,我可能会构建&&部署&&启动我的应用程序然后出去吃午饭。该过程可能需要 15 分钟才能完成。但是自从我用&&,如果构建失败,它就不会部署——这样就可以了。
预先输入是一种替代方法,但它是不确定的,您可能无法看到您输入的内容(因此会犯错误),或者程序可能会吃掉预先输入的内容(谢谢,grails!)。然后你吃完午饭回来,发现由于打字错误,你还有两个很长的任务要开始。
另一种选择是编写一个小脚本或别名。不错的主意,但不允许有很大的灵活性,就像我可以:
stop && build && test && deploy && start
Run Code Online (Sandbox Code Playgroud)
或者我可以:
stop && start
Run Code Online (Sandbox Code Playgroud)
或者任何数量的其他组合会用一堆标志迅速污染脚本。
即使您确实编写了一个脚本,您也很可能将它与其他带有&&.
小智 10
在 Linux 上组合命令非常有用。
一个很好的例子可能是通过 ssh 重新启动远程网络接口(如果您更改了网络配置或其他内容...)。
ifdown eth0 && ifup eth0
Run Code Online (Sandbox Code Playgroud)
这可以防止您物理上访问服务器以打开您最初通过 ssh 连接到的界面。(ifup eth0如果ifdown eth0单独执行,您将无法执行。)
为了理解原因,我们还需要了解正在做什么。脚本是连续的。在你的最后一个例子中:
mkdir build
cd build
touch blank.txt
Run Code Online (Sandbox Code Playgroud)
cd build无论mkdir build成功与否,都会被执行。当然如果mkdir fails,你会看到错误来自cd.
mkdir build; cd build; touch blank.txt是一个顺序列表。这可以被认为与多个脚本行基本相同。Shell Grammar 将对此略有不同,但结果将与上述完全相同。同样,无论先前是否成功,都会执行命令。
最后,有
mkdir build && cd build && touch blank.txt
Run Code Online (Sandbox Code Playgroud)
这是一个AND 列表- 由&&运算符分隔的一个或多个管道(或命令)的序列。此类列表中的命令以左关联性执行。这意味着,shell 将继续采用由 分隔的两个命令/管道&&,首先在左边执行一个,只有在左边一个成功时才运行右边的一个(返回零退出状态)。
在这个例子中,会发生什么?
mkdir build首先执行。cd build将运行... && touch blank.txt. 左边的东西&&成功了吗?如果是,请运行touch blank.txt。mkdir build; cd build; touch blank.txt当我们对其中一个命令失败没有问题时,顺序列表是有意义的。假设mkdir build已经存在。我们仍然要cd进入build/目录和touch blank.txt. 当然,这里的缺点是有可能出现意想不到的结果。如果build没有设置执行位怎么办,这就是cd build失败的原因?该touch blank.txt会在我们当前的工作目录,而不是预期的发生build/。
现在考虑mkdir build && cd build && touch blank.txt。这在某种程度上更合乎逻辑,但也有其自身的缺陷。如果build已经存在,可能有人也已经这样做了touch blank.txt,所以我们可能不想再做touch blank.txt,因为这会修改它的访问时间戳,这可能是不可取的。
将命令放在同一行上取决于命令的目的和您要实现的目标。顺序列表可以简化输出,因为在命令完成之前,shell 不会重新显示提示。AND 列表允许有条件地执行命令,并可以防止执行不必要的命令。底线是用户需要知道差异以及选择什么作为任务的正确工具。
另一个原因可能与脚本的形成方式有关:技术用户通常会构建很长的交互式命令行,反复扩展和测试它们直到它们按预期工作,然后将结果粘贴到文本文件中并添加#!/bin/bash标题超过它。有时脚本的多个部分是通过这种方法演变的。
以for i in、grep | cut | sed | xargs链开头、大量使用&&和||、$(cat something)结构的长单行结构通常表示这种起源。
| 归档时间: |
|
| 查看次数: |
18006 次 |
| 最近记录: |