相关疑难解决方法(0)

忘记在 bash/POSIX shell 中引用变量的安全隐患

如果您已经关注 unix.stackexchange.com 一段时间了,那么您现在应该知道,echo $var在 Bourne/POSIX shell(zsh 是例外)中的列表上下文(如)中不加引号的变量具有非常特殊的含义,并且除非你有很好的理由,否则不应该这样做。

在这里的许多问答中详细讨论了它(例如:为什么我的 shell 脚本会因空格或其他特殊字符而窒息?何时需要双引号?shell 变量的扩展以及 glob 和 split 对其的影响引用vs 不带引号的字符串扩展)

自从 70 年代末 Bourne shell 首次发布以来就是这种情况,并且没有被 Korn shell 改变(David Korn 最大的遗憾之一(问题 #7))或者bash大部分复制了 Korn shell,这就是POSIX/Unix 是如何指定的。

现在,我们仍然在这里看到许多答案,甚至偶尔会公开发布未引用变量的 shell 代码。你会认为人们现在已经学会了。

根据我的经验,主要有 3 类人会省略引用他们的变量:

  • 初学者。这些可以被原谅,因为它是一种完全不直观的语法。我们在这个网站上的职责是教育他们。

  • 健忘的人。

  • 即使经过反复锤击也不相信的人,他们认为Bourne shell 的作者肯定没有打算让我们引用所有变量

如果我们揭露与此类行为相关的风险,也许我们可以说服他们。

如果您忘记引用变量,那么最糟糕的事情是什么。真的有那么糟糕吗?

我们在这里谈论什么样的漏洞?

在什么情况下会出现问题?

shell security bash shell-script quoting

241
推荐指数
3
解决办法
3万
查看次数

为什么我需要为 if 引用变量,而不是为 echo 引用?

我读过你需要双引号来扩展变量,例如

if [ -n "$test" ]; then echo '$test ok'; else echo '$test null'; fi
Run Code Online (Sandbox Code Playgroud)

将按预期工作,而

if [ -n $test ]; then echo '$test ok'; else echo '$test null'; fi
Run Code Online (Sandbox Code Playgroud)

总是会说$test ok即使$test为空。

但是为什么我们不需要引号echo $test呢?

shell quoting

29
推荐指数
2
解决办法
9765
查看次数

读取命名管道:tail 还是 cat?

我使用了一个文件描述符

mkfifo fifo
Run Code Online (Sandbox Code Playgroud)

一旦有东西写入这个管道,我想立即重用它。我应该使用

tail -f fifo
Run Code Online (Sandbox Code Playgroud)

或者

while true; do cat fifo; done
Run Code Online (Sandbox Code Playgroud)

?

他们似乎做同样的事情,我无法衡量性能差异。但是,当系统不支持inotify(例如Busybox)时,前者需要

tail -f -s 0 fifo
Run Code Online (Sandbox Code Playgroud)

但这会以 100% 的使用率消耗 CPU(测试一下:mkfifo fifo && busybox tail -f -s 0 fifo & echo hi>fifo/ 用fg 1和取消CtrlC)。那么 while-true-cat 是更可靠的解决方案吗?

pipe tail cat fifo

8
推荐指数
1
解决办法
4496
查看次数

Bash:从子 shell 写入全局变量

我正在尝试将一些getopts逻辑转移到函数中,这样我就可以多次使用它,从而为用户指定参数的顺序提供更大的灵活性:

print-usage() {
echo "myssh [options] <host> [options] [-- ssh-options...]" >&2
exit 1
}

extra_args=()

parse-args() {
  while getopts ":hvV:" opt; do
    case ${opt} in
      (h)  print-usage ;;
      (v)  extra_args+=('-L 5900:localhost:5900')    ;;
      (V)  extra_args+=("-L $OPTARG:localhost:5900") ;;
      (\?) echo "Invalid option: -$OPTARG" >&2       ;;
      (:)  echo "Invalid option: -$OPTARG requires an argument" >&2 ;;
    esac
  done
  echo $((OPTIND -1))
}

shift $(parse-args $@)

host=$1
shift

shift $(parse-args $@)

ssh $host $extra_args $@

Run Code Online (Sandbox Code Playgroud)

我的问题是这parse-args() { ... extra_args+=(...) }不会影响全局变量 …

bash

5
推荐指数
1
解决办法
2223
查看次数

标签 统计

bash ×2

quoting ×2

shell ×2

cat ×1

fifo ×1

pipe ×1

security ×1

shell-script ×1

tail ×1