ChatGPT解决这个技术问题 Extra ChatGPT

Bash:语法错误:重定向意外

我在脚本中执行此操作:

read direc <<< $(basename `pwd`)

我得到:

Syntax error: redirection unexpected

在 ubuntu 机器中

/bin/bash --version
GNU bash, version 4.0.33(1)-release (x86_64-pc-linux-gnu)

虽然我在另一台 suse 机器上没有收到此错误:

/bin/bash --version
GNU bash, version 3.2.39(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

为什么会出错?

作为参考,该命令也适用于 cygwin ( /bin/bash --version GNU bash, version 3.2.49(23)-release (i686-pc-cygwin) 版权所有 (C) 2007 Free Software Foundation, Inc. )

J
John Kugelman

您的脚本是否在其 hash bang 行中引用了 /bin/bash/bin/sh? Ubuntu 中的默认系统 shell 是 dash,而不是 bash,因此如果您有 #!/bin/sh,那么您的脚本将使用与您预期不同的 shell。 Dash 没有 <<< 重定向运算符。

确保 shebang 线是:

#!/bin/bash

或者

#!/usr/bin/env bash

并使用以下命令运行脚本:

$ ./script.sh

not 使用显式 sh 运行它,因为这将忽略 shebang:

$ sh ./script.sh   # Don't do this!

我在 sh 文件顶部有“#!/bin/bash”,但它仍然给出该错误。正如@chris 所说,它在使用 bash ./script.sh 时有效。
@ibilgen 您是否使用 sh ./script.sh 运行它?不要使用显式 shell 运行脚本。只需键入脚本名称 ./script.sh,它就可以使用在 shebang 行中声明的解释器。
我应该将默认 shell dash 更改为 bash 吗?
@kittygirl 我刚刚从 '/bin/sh' 更改为 '/bin/bash' 并且它有效!
不,不要更改默认外壳。这是脚本中的错误/脚本的运行方式。 Don't make global changes to fix a local problem.
C
Chris Pietschmann

如果您使用以下内容运行脚本:

sudo sh ./script.sh

然后,您将要使用以下内容:

sudo bash ./script.sh

原因是 Bash 不是 Ubuntu 的默认 shell。因此,如果您使用“sh”,那么它将只使用默认 shell;这实际上是 Dash。无论您的脚本顶部是否有 #!/bin/bash,都会发生这种情况。因此,您需要明确指定使用 bash,如上所示,并且您的脚本应该按预期运行。

Dash 不支持与 Bash 相同的重定向。


T
Toby Speight

码头工人:

我从我的 Dockerfile 中遇到了这个问题:

RUN bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

但是,根据this issue,它已解决:

exec 形式可以避免 shell 字符串修改,并使用不包含 /bin/sh 的基本映像运行命令。注意 要使用 /bin/sh 以外的其他 shell,请使用传入所需 shell 的 exec 形式。例如,运行 ["/bin/bash", "-c", "echo hello"]

解决方案:

RUN ["/bin/bash", "-c", "bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)"]

注意每个参数周围的引号。


这使我可以让 here-string 在 Dockerfile 中运行。对“覆盖问题”说“是”(y)需要这个字符串(不重要:它用于 ssh-keygen -q -t rsa <<< ""$'\n'"y",参见 stackoverflow.com/a/43235320/11154841)。
A
AmirHossein

您可以获取该命令的输出并将其放入变量中。然后使用 heredoc。例如:

nc -l -p 80 <<< "tested like a charm";

可以写成:

nc -l -p 80 <<EOF
tested like a charm
EOF

像这样(这就是你想要的):

text="tested like a charm"
nc -l -p 80 <<EOF
$text
EOF

docker 容器下 busybox 中的实际示例:

kasra@ubuntu:~$ docker run --rm -it busybox
/ # nc -l -p 80 <<< "tested like a charm";
sh: syntax error: unexpected redirection


/ # nc -l -p 80 <<EOL
> tested like a charm
> EOL
^Cpunt!       => socket listening, no errors. ^Cpunt! is result of CTRL+C signal.


/ # text="tested like a charm"
/ # nc -l -p 80 <<EOF
> $text
> EOF
^Cpunt!

...或 echo 'text' | nc 更短。
g
ghostdog74

用更简单的方法,

direc=$(basename `pwd`)

或者使用外壳

$ direc=${PWD##*/}

M
Motin

该错误的另一个原因可能是如果您正在运行更新颠覆工作副本的 cron 作业,然后尝试运行在更新后处于冲突状态的版本化脚本......


M
Milo

在我的机器上,如果我直接运行脚本,默认为 bash

如果我使用 sudo 运行它,则默认值为 sh

这就是我在使用 sudo 时遇到此问题的原因。


l
luk2302

在我的情况下,错误是因为我放了两次“>>”

mongodump --db=$DB_NAME --collection=$col --out=$BACKUP_LOCATION/$DB_NAME-$BACKUP_DATE >> >> $LOG_PATH

我只是纠正它

mongodump --db=$DB_NAME --collection=$col --out=$BACKUP_LOCATION/$DB_NAME-$BACKUP_DATE >> $LOG_PATH

S
Sijeesh

在运行脚本之前,您应该检查解释器的 shell 脚本的第一行。

例如:如果脚本以 /bin/bash 开头,请使用以下命令“bash script_name.sh”运行脚本

如果脚本以 /bin/sh 开头,请使用以下命令“sh script_name.sh”运行脚本

./sample.sh - 这将从脚本的第一行检测解释器并运行。

不同的 Linux 发行版默认具有不同的 shell。


尽管我们感谢您的回答,但如果它在其他答案之上提供额外的价值会更好。在这种情况下,您的答案不会提供额外的价值,因为另一个用户已经发布了该解决方案。如果之前的答案对您有帮助,您应该投票而不是重复相同的信息。
你不认为我在这里用一个例子解释了解决方案吗?
8 年前写的 John Kugelman's answer 中是否有任何内容没有充分涵盖?