当我们编写 shell 脚本时,我们这样做:
#!/bin/bash
Run Code Online (Sandbox Code Playgroud)
但是如果 bash 在里面/usr/bin/呢?我们如何在脚本中以可移植的方式找到它?我这样做了,但它给出了错误:
#!which bash
Run Code Online (Sandbox Code Playgroud) 如果我可以在我的 bash shell 中做到这一点:
$ STRING="A String"
$ echo ${STRING^^}
A STRING
Run Code Online (Sandbox Code Playgroud)
如何将命令行参数更改为大写?
我试过:
GUARD=${1^^}
Run Code Online (Sandbox Code Playgroud)
该行产生该行的错误替换错误。
在运行setuid启用位的程序时,我观察到一个奇怪的行为。
程序foo由bar设置了 setuid 位的用户拥有。
用户execbar运行foo
foo 报告动态库之一无法访问。
有问题的动态库位于正常ld.so.conf搜索路径之外的目录中,因此它是通过LD_LIBRARY_PATH为用户设置的execbar
问题是:运行程序是否setuid清除了用户设置的环境execbar?
我注意到对于bash脚本,有些人使用了与我习惯放在自己顶部的不同的
shebang。
有人可以简化这两者之间的区别吗?我一直用那个#!/bin/bash。
#!/bin/bash
#!/usr/bin/env bash
Run Code Online (Sandbox Code Playgroud) 编辑: 问题和答案是正确的,但我在这里陈述的问题不是。维护者实际上拒绝将其/usr/bin/env用作解决方案,而是将脚本重新创建为一个脚本sh,这样做会破坏其他用户的安装。因此,env用于查找bash不是 POSIX,而是默认“足够”被视为标准。
我在 nixos(特别是haskell 堆栈)上安装软件时遇到了一些错误,在互联网上进行了一些挖掘之后,我发现了一些人们在安装软件的特定路径时遇到问题的例子。这是一个示例,其中维护人员/usr/bin/env在查找 bash 时恢复了对解决方案的修改,因为它破坏了其他用户的安装。
那么,env在没有告知安装的绝对路径(依靠系统搜索路径)的情况下引用shebang是否可以被认为是错误的?
我的意思是可以使用
#!env bash
Run Code Online (Sandbox Code Playgroud)
代替
#!/usr/bin/env bash
Run Code Online (Sandbox Code Playgroud)
如果安装的绝对路径env不是所有系统上的默认值?
我在另一个答案中读到,我无法将参数传递给解释器,而不是我给出的/usr/bin/env:
另一个潜在的问题是该
#!/usr/bin/env技巧不允许您将参数传递给解释器(除了脚本的名称,它是隐式传递的)。
但是,看起来我能够做到,因为awk当我不给它-f标志时它会损坏,而当我给它标志时它会被修复-f,同时使用/usr/bin/env:
首先,没有-f标志:
$ cat wrap_in_quotes
#!/usr/bin/env awk
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
awk: syntax error at source line 1
context is
>>> . <<< /wrap_in_quotes
awk: bailing out at source line 1
Run Code Online (Sandbox Code Playgroud)
二、带-f旗:
$ vim wrap_in_quotes
$ cat wrap_in_quotes
#!/usr/bin/env awk -f
# …Run Code Online (Sandbox Code Playgroud) 例如:
$ cat foo.sh
#!/usr/bin/env bash
while true; do sleep 1 ; done
$ ./foo.sh &
$ pgrep foo.sh
$
Run Code Online (Sandbox Code Playgroud)
对比:
$ cat bar.sh
#!/bin/bash
while true; do sleep 1 ; done
$ ./bar.sh &
$ pgrep bar.sh
21202
Run Code Online (Sandbox Code Playgroud)
由以下命令启动的进程env bash显示在输出中ps aux:
terdon 4203 0.0 0.0 26676 6340 pts/3 S 17:23 0:00 /bin/bash
Run Code Online (Sandbox Code Playgroud)
而开头的/bin/bash显示为
terdon 9374 0.0 0.0 12828 1392 pts/3 S 17:27 0:00 /bin/bash ./bar.sh
Run Code Online (Sandbox Code Playgroud)
这可能解释了为什么它第一个没有被 捕获pgrep。所以,问题是:
env?阅读env POSIX 文档:
有些人认为 env 是多余的,因为通过以下方式实现了相同的效果:
名称=值 ... 实用程序 [ 参数 ... ]
当将环境变量添加到命令的环境中时,该示例等效于 env,但在将环境设置为给定值时则不一样。如果不带参数调用 env 实用程序还会写出当前环境。除了示例提供的功能之外,还有足够的功能来证明包含 env 是合理的。
AFAICT,上述语句的含义var=value command将与 相同env var="value" command,而在使用 as 时则不同env -i var="value" command。
现在,至少在envGNU系统上实现,FreeBSD和Solaris 11中,我才知道他们是不等价的,因为env允许任何字符,除了=和\0在var名称:
$ env 'BASH_FUNC_foo%%=() { echo foo; }' bash -c foo
Run Code Online (Sandbox Code Playgroud)
打印foo,而您不能BASH_FUNC_foo%%='() { echo foo; }'在任何 shell 中使用,因为BASH_FUNC_foo%%显然不是有效的变量名。
在 POSIX shell 中,除了bash,这会留下一个BASH_FUNC_foo%%在环境变量中命名的变量,shell …
我收到错误
/usr/bin/env: zsh -: No such file or directory
Run Code Online (Sandbox Code Playgroud)
...当我运行以zsh以下shebang行开头的可执行脚本时:
#!/usr/bin/env zsh -
Run Code Online (Sandbox Code Playgroud)
此外,FWIW,替换-为--原因/usr/bin/env打印关于zsh --.
我只在 ubuntu 下看到过这个错误,而且只在 shebang hack 的上下文中看到过。在达尔文下,相同的脚本运行良好。在 ubuntu 下,运行
% /usr/bin/env zsh -
Run Code Online (Sandbox Code Playgroud)
从命令行成功。(实际上,“在 ubuntu 下”应该理解为“在 ubuntu 12.04 LTS 和env (GNU coreutils) 8.13”下的简写。)
我的问题是:如何修改上面的shebang以避免此错误?
当然,我知道删除尾随-会消除错误,但这不是一个可以接受的解决方案。这篇文章的其余部分解释了原因。
导致错误的 shebang 行是为了遵守两个完全独立的准则:
要使脚本可移植,请使用#!/usr/bin/env <cmd ...>而不是#!/path/to/cmd <...>.
把-作为唯一参数zsh在zsh的脚本横座板某类的家当线的攻击。
所以,我可以更准确地重申我的问题如下:是否有可能同时满足这两个准则而不会在 ubuntu 下触发上面显示的错误?
所以我知道我可以将 she-bangs 更改为,#!/usr/bin/env bash并且我将为我的脚本执行此操作,但实际上我希望能够使用#!/bin/bashshe-bang 运行许多脚本。有时很容易更改,有时则不然,因为脚本是由其他东西运行的,而不是由您直接运行,并且它位于您真正不想触及的地方。
我可以在系统配置中启用一些选项来获取链接/bin/bash,还有什么原因我不应该这样做,为什么这不是标准?(请不要告诉我有关滑坡的事情,/bin/bash这可能是对 Unix 系统最常见的假设之一)
shebang 标头必须始终与解释器的安装目录匹配吗?如果是这样,那么为什么既#!/usr/bin/python和#!/usr/local/bin/python我的工作?