你可以用eval命令做什么?为什么有用?它是 bash 中的某种内置函数吗?没有man它的页面。。
为了运行,ssh-agent我必须使用:
eval $(ssh-agent)
Run Code Online (Sandbox Code Playgroud)
为什么需要eval输出ssh-agent? 为什么我不能运行它?
我想列出机器上的所有用户目录。通常,我会这样做:
ls -l /home
Run Code Online (Sandbox Code Playgroud)
但是我在一个脚本中使用它,该脚本将部署在其他机器上,也许在他们不称之为家的机器上(例如 myHome)。所以我想把它概括为ls -l ~. 但它只列出我的用户主目录而不是所有用户主目录名称(基本上我想获得机器上用户名的列表)。我怎样才能概括它?
您经常听到它eval is evil,无论是在 Shell/POSIX 世界中,还是在其他语言(如 python 等)中...
但我想知道,它真的没用吗?或者是否有一些神秘的、未记录的、有趣的或只是有用的用例?
如果答案以sh/bash为中心,我会更喜欢,但如果它也与其他壳有关,那也没关系。
考虑命令
eval false || echo ok
echo also ok
Run Code Online (Sandbox Code Playgroud)
通常,我们希望它执行false实用程序,并且由于退出状态非零,然后执行echo ok和echo also ok。
在我使用的所有类似 POSIX 的 shell(ksh93、zsh、bash、dash、 OpenBSDksh和yash)中,都会发生这种情况,但是如果我们启用set -e.
如果set -e有效,OpenBSDsh和kshshell(均源自pdksh)将在执行eval. 没有其他外壳能做到这一点。
POSIX 表示特殊内置实用程序(例如eval)中的错误应导致非交互式 shell 终止。我不完全确定执行是否false构成“错误”(如果是,则与set -e活动无关)。
解决此问题的方法似乎是将其放入eval子外壳中,
( eval false ) || echo ok
echo also ok
Run Code Online (Sandbox Code Playgroud)
问题是我是否需要在 POSIX-ly 正确的 …
我已经使用docker了一段时间,每次启动 docker 时都会写一个命令:
eval $(docker-machine env)
Run Code Online (Sandbox Code Playgroud)
我知道eval除非必要,否则不应使用,但以下提到了它:
docker-machine env 输出这样的环境变量:
docker-machine env
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://<some_ip>:<some_port>"
export DOCKER_CERT_PATH="/home/gableroux/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell:
# eval $(docker-machine env)
Run Code Online (Sandbox Code Playgroud)
eval 抓住这些并将它们加载到我当前的会话中。
现在如果我想要一个这样的别名怎么办:
alias dockereval="eval $(docker-machine env)"
Run Code Online (Sandbox Code Playgroud)
语法很好,但问题是当一个 dotfile(让我们.zshrc举个例子)时,$()当你注册source那个文件的别名时,它的内容会被评估。
which dockereval
Run Code Online (Sandbox Code Playgroud)
结果是
dockerenv: aliased to eval
Run Code Online (Sandbox Code Playgroud)
我尝试了一些事情,例如:
alias dockereval="docker-machine env | eval"
alias dockereval="docker-machine env | /bin/bash"
alias dockereval="eval `docker-machine env`"
Run Code Online (Sandbox Code Playgroud)
但没有一个工作。第二个可能是因为它在不同的会话中运行,第三个和$()我猜的一样
还有其他方法可以使用别名加载这些环境变量吗?
bash 手册指出:
eval [arg ...]
The args are read and concatenated together into a single com-
mand. This command is then read and executed by the shell, and
its exit status is returned as the value of eval. If there are
no args, or only null arguments, eval returns 0.
Run Code Online (Sandbox Code Playgroud)
我试试
eval `nonsense`
echo $?
Run Code Online (Sandbox Code Playgroud)
结果是0。
而当我单独执行反引号命令时:
`nonsense`
echo $?
Run Code Online (Sandbox Code Playgroud)
结果是127。
从什么是写在bash的手册我希望eval以回报127服用后引号时nonsense作为参数。
如何获取参数的退出状态eval?
该站点上的许多答案和评论都提到通常应避免eval在 shell 脚本中使用。这些评论通常是针对初学者的。
我已经看到提到安全问题和健壮性,但很少有例子。
我已经明白命令是什么,以及如何使用它eval。但是,那里给出的答案仅简要提及使用eval. 值得注意的是,每个答案都指出这eval可能是一个主要的安全漏洞,但大多数只是将这一事实作为结束语而没有详细说明。这似乎值得进一步考虑,实际上是它自己的问题。
为什么是用eval一个坏主意?
当将它适当地使用?
是否有任何指导方针可以完全安全地使用它,或者它总是不可避免地存在安全漏洞?
编辑:这篇文章是我在发布这个问题时实际寻找的那种规范参考(答案)。任何滥用的人eval都可以指向此参考。
当我在看这个答案/sf/answers/774563751/以弄清楚如何使用参数时,--something或者-s关于答案脚本的一些问题:
#!/bin/bash
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
-n 'example.bash' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-a|--a-long) echo "Option a" ; shift ;;
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
-c|--c-long)
# c has an optional argument. As we …Run Code Online (Sandbox Code Playgroud) 我有一个shell 变量,其中包含由空格分隔的多个单词bash组成的字符串。字符串可以包含转义符,例如单词中转义的空格。包含空格的单词也可以被引用。
$FOO不加引号(而不是)使用的 shell 变量"$FOO"会变成多个单词,但原始字符串中的引号和转义不起作用。
如何将字符串拆分为单词,同时考虑引用字符和转义字符?
服务器提供ssh使用文件ForceCommand中的选项来sshd_config强制执行脚本的受限访问,而不管向客户端提供的命令行如何ssh。
该脚本使用变量SSH_ORIGINAL_COMMAND(它是一个字符串,由 设定ssh,包含提供给客户端的命令行ssh)在继续之前设置其参数列表。所以,用户做
$ ssh some_server foo 'bar car' baz
Run Code Online (Sandbox Code Playgroud)
将看到脚本执行,并且当脚本执行时它将设置为四个SSH_ORIGINAL_COMMAND参数foo bar car baz
set -- ${SSH_ORIGINAL_COMMAND}
Run Code Online (Sandbox Code Playgroud)
不是想要的结果。于是用户再次尝试:
$ ssh some_server foo bar\ car baz
Run Code Online (Sandbox Code Playgroud)
相同的结果 - 第二个参数中的反斜杠需要为客户端 shell 进行转义,以便ssh看到它。这些怎么样:
$ ssh some_server foo 'bar\ car' baz
$ ssh some_server foo bar\\ car baz
Run Code Online (Sandbox Code Playgroud)
两者都可以工作,就像可以简化客户端引用的printf "%q"引用包装器一样。 …