AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 688976
Accepted
E235
E235
Asked: 2022-02-03 03:19:52 +0800 CST2022-02-03 03:19:52 +0800 CST 2022-02-03 03:19:52 +0800 CST

仅使用“sh -c”调用 shell 脚本时出错:“意外运算符”

  • 772

我有以下脚本:

installRequiredFiles=$1

install_with_pkg()
{
    arg1=$1
        echo $arg1
    echo "[+] Running update: $arg1 update."
}

if [ $installRequiredFiles = "true" ]; then
    if [ -x "$(command -v apt)" ]; then
          install_with_pkg "apt"
        elif [ -x "$(command -v yum)" ]; then
          install_with_pkg "yum"
        elif [ -x "$(command -v apk)" ]; then
          install_with_pkg "apk"
        else
          echo "[!] Can't install files."
    fi
fi

当我直接运行它时,它工作正常:

root@ubuntu:/# ./myscript.sh "true"
apt
[+] Running update: apt update.
Printing installRequiredFiles: true
Printing arg1: apt

但是当我使用时,sh -c我收到以下错误:

root@ubuntu:/# sh -c ./myscript.sh "true"
./c.sh: 11: [: =: unexpected operator
Printing installRequiredFiles:
Printing arg1:

我希望能够正确运行它,sh -c并且我希望它支持sh并且bash目前支持。

linux shell-script
  • 2 2 个回答
  • 248 Views

2 个回答

  • Voted
  1. Best Answer
    terdon
    2022-02-03T03:43:52+08:002022-02-03T03:43:52+08:00

    这不是-c选项的用途。你通常不给它一个文件,你给它shell命令。它用于执行以下操作:

    $ sh -c 'echo hello'
    hello
    

    现在你给了它一个文件,它正在尝试读取它并执行在其中找到的命令,但是参数没有传递给脚本(myscript.sh),参数只提供给sh命令本身,你可以看到只需打印参数:

    $ cat script.sh
    echo "ARGS: $@"
    
    $ sh ./script.sh true
    ARGS: true
    $ sh -c ./script.sh true
    ARGS: 
    

    您需要做的就是不使用-c它,它会按预期工作:

    sh ./myscript.sh "true"
    

    或者,如果您-c出于某种原因绝对必须使用,请将脚本和脚本的参数作为单个带引号的参数传递给sh:

    sh -c './myscript.sh "true"'
    
    • 5
  2. they
    2022-02-03T05:17:18+08:002022-02-03T05:17:18+08:00

    您得到的错误来自dash外壳程序(用于/bin/sh在您的系统上实现的外壳程序)。这是由于$installRequiredFiles被

    1. 一个空字符串,和
    2. 使用未引用。

    由于变量是空的,使用它不带引号将其完全从命令中删除,这意味着该行

    if [ $installRequiredFiles = "true" ]; then
    

    将被解释为

    if [ = "true" ]; then
    

    这又是[命令使用中的错误;=当不需要操作员时,它会看到操作员。

    那么,为什么$installRequiredFiles(和$1)是空的?

    命令

    sh -c ./myscript.sh "true"
    

    运行命令./myscript.sh并$0设置为脚本中的字符串true。in 的值$0通常是脚本或shell 的名称,该值最常用于诊断消息(例如,在shell 产生的错误消息中)。

    如果你用过

    sh -c ./myscript.sh sh "true"
    

    相反,then$1会test按预期设置为,并且$0会设置为(这对于内联脚本sh来说是惯用的)。在这两种情况下,脚本都将由任何不带-linesh -c的 shell 执行脚本来执行。#!最终运行脚本的shshell 可能取决于您机器上的 shell,它可能不是shor bash。参见,例如,哪个 shell 解释器运行没有 shebang 的脚本?.

    您可能希望#!在脚本中添加一个 -line 指向/bin/sh:

    #!/bin/sh
    
    # ... rest of script here ...
    # ... just remember to quote all expansions ...
    

    这意味着您将能够像这样运行您的脚本:

    $ ./myscript.sh test
    

    或者,与等价的

    $ sh -c './myscript.sh "test"'
    

    或者,

    $ sh -c './myscript.sh "$@"' sh test
    

    请注意,在最后两种情况下,sh -c执行脚本的不是 shell,而是脚本中的#!-line 所指的任何 shell,就像您./myscript.sh "test"直接运行一样。与添加 -line 之前相比,不同之#!处在于您现在可以确定这是/bin/sh而不是其他一些 shell。

    该脚本仅使用 POSIX shell 语法,这意味着它可以由 执行,而不管在任何给定系统上/bin/sh使用什么 shell 来实现。/bin/sh如果/bin/shisbash或ksh其他dash更奇特的 shell 无关紧要,用户不必担心使用正确的解释器运行脚本。

    与此答案的各个部分相关:

    • 什么时候需要双引号?
    • `sh -c` 的 `name` 参数是什么?
    • 哪个 shell 解释器运行没有 shebang 的脚本?
    • 3

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 按分隔符拆分并连接字符串问题

  • astyle 不会更改源文件格式

  • MySQL Select with function IN () with bash array

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve