奇怪的 bash 脚本行为 - 生成的命令在复制粘贴时有效,但在脚本中无效

2024-04-23

出于安全原因,我编写了一个简短的 bash 脚本来包装 ansible playbook 命令。这并不复杂,而且大部分脚本在这里都是无关紧要的。最后,我将脚本参数生成的变量中的 ansible 命令放在一起,如下所示:

ansible-playbook -k $user -i hosts-staging $limit $tags $additionalargs site.yml  

生成的命令在大多数情况下都有效,但 $additionalargs 似乎没有任何效果。所以我做了一个回显并查看脚本实际生成的内容:

echo ansible-playbook -k $user -i hosts-staging $limit $tags $additionalargs site.yml

output: ansible-playbook -k -u pi -i hosts-staging -l tcameras --tags fulllaunch --extra-vars "agraphite_force_restart=true" site.yml

这看起来完全符合预期,但 --extra-vars 参数似乎没有被传递。 因此,我复制了 echo 生成的行,将其粘贴到控制台中并按 Enter 键,这完全有效,包括 --extra-vars 参数。

因此,脚本生成了我想要的内容,如果我手动提供脚本生成的命令,它就可以工作......但是当脚本本身执行命令时,它就不起作用,或者至少不完全。

有人可以给我一个提示,告诉我可能会出什么问题吗?下面是供参考的完整脚本,尽管由于输出符合预期,我不希望问题出现在此处,而是有一些我不知道的 bash 特殊性。

#!/bin/bash

# brief         Makes graphite deployment via Ansible saver by wrapping it into a script that only needs the most common variables, does not apply to the whole inventory by default, and uses the current staging inventory.
# args (3)      Expects 3 arguments: what to do, who to do it with, and if it should do it with all of them or just with one individual instance
# arg $1        What to do. Valid values are "deploy", "launch" or "restart".
# arg $2        Who to do it with. Valid values are "cameras", "servers" or "all".
# arg $3        Optional: Pass an IP from the inventory to apply the action to.     

# error codes:
# 1: Unexpected number of arguments
# 2: Invalid first argument
# 3: Invalid second argument
# 4: Invalid third argument (optional)
# 5: Optional third argument not compatible with second argument

additionalargs=""

if [ $# -lt 2 ]; then
    echo "Unexpected number of arguments (2 expected). Please pass what (\"deploy\", \"launch\" or \"restart\") and who (\"cameras\", \"servers\" or \"all\")"
    exit 1
fi

if [ $1 == "launch" ]; then
    tags="--tags fulllaunch"
elif [ $1 == "restart" ]; then
    tags="--tags fulllaunch"
    additionalargs='--extra-vars "agraphite_force_restart=true"'
elif [ $1 != "deploy" ]; then
    echo "Invalid argument: "$1"! Must be either \"launch\", \"deploy\" or \"restart\"!"
    exit 2
else
    tags=""
fi

if [ $2 == "cameras" ]; then
    limit="-l tcameras"
    user="-u pi"
elif [ $2 == "servers" ]; then
    limit="-l tservers"
    user="-u ubuntu"
elif [ $2 == "all" ]; then
    limit=""
    user="both"
else 
    echo "Invalid argument: "$2"! Must be either \"cameras\", \"servers\", <ip> or \"all\"!"
    exit 3
fi

if [ $# -eq 3 ]; then
    if [[ $3 == *.*.*.* ]]; then              #quite a superficial check for the validity of an ip address, but it serves to prevent dangerous input
        limit="-l "$3
    else
        echo "Error: optional third parameter must be a valid ip-address!"
        exit 4
    fi
    if [ $user == "both" ]; then
        echo "Error: specific ip cannot be used with parameter \"all\"."
        exit 5   
    fi
fi    


if [[ $user == "both" ]]; then
    #do actions for both cameras and servers
    ansible-playbook -k -u ubuntu -i hosts-staging -l tcameras $tags $additionalargs site.yml 
    ansible-playbook -k -u pi -i hosts-staging -l tservers $tags $additionalargs site.yml 
else
    echo ansible-playbook -k $user -i hosts-staging $limit $tags $additionalargs site.yml
    ansible-playbook -k $user -i hosts-staging $limit $tags $additionalargs site.yml  
fi

我在编写另一个涉及相当复杂的curl命令的脚本时找到了这个问题的解决方案。 首先我发现你可以使用

set -x

在脚本中让它显示扩展的命令,我对引用扩展产生的混乱感到相当震惊。它在回声中很好地扩展了,但是将整个事情作为参数传递,构建了一个神秘的引号迷宫。我还尝试过引用变量,但 Ansible 不太喜欢这样。

我发现,对于带有许多参数且本身可能包含引号的长命令,最好将整个命令写在双引号内的字符串中,并转义参数内的任何引号,然后将整个命令传递给 eval。

在这种特殊情况下,实际工作的命令如下所示:

eval "ansible-playbook -k $user -i hosts-staging $limit $tags $additionalargs site.yml"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

奇怪的 bash 脚本行为 - 生成的命令在复制粘贴时有效,但在脚本中无效 的相关文章

  • 将多个参数传递给 UNIX shell 脚本

    我有以下 bash shell 脚本 理想情况下我会用它来按名称杀死多个进程 bin bash kill ps A grep awk print 1 然而 虽然此脚本有效 但传递了一个参数 端镀铬 脚本名称为end 如果传递多个参数 则它不
  • 验证 BASH 脚本时出现问题 [已关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我在尝试验证 bash 脚本时出现代码 lint 错误 bin bash if eq 0 then printf No argum
  • Bash 脚本重定向不起作用,为什么? [复制]

    这个问题在这里已经有答案了 我最近在 bash 脚本中发现了意外行为 我想在解决它之前先了解它 这是一个简化的示例 bin sh SCRIPT tmp echoscript sh gt gt tmp log bin sh SCRIPT ec
  • bash 用变量值替换字符串中的变量名

    这有点奇怪 我有以下字符串 我有一个名为 REDIRECT 的变量设置为 https working MYDOMAIN blah blah 我需要将 MYDOMAIN 替换为分配给 MYDOMAIN 的变量的实际值 不确定 bash 还是
  • 在 UNIX 时间戳 Shell/Bash 中将日期与时区转换

    我需要将日期从格式为 yyyy mm dd hh mm ss TZ 的字符串转换为 UNIX 时间 TZ 时区 到目前为止我所做的是将没有时区的 yyyy mm dd hh mm ss 格式的日期转换为时间戳 dateYMD 2019 2
  • Ansible 和硬件检查

    我必须使用 ansible 检查 Linux 机器上的不同硬件和配置元素 我完全不确定如何做到这一点 RAM 磁盘空间 DNS CPU 我知道我几乎可以找到我想要的所有事实都在 ansible 中 但我不明白如何使用它 例如 我必须检查 R
  • Unix cURL POST 使用文件中的内容到特定变量

    我已经搜索过这个答案 但没有找到任何有效或完全符合我的问题的答案 使用 Unix cURL 我需要将键 值对发布到服务器 密钥将是 MACs 换行符分隔的 MAC 地址文件的内容将是此 POST 的 VALUE 我试过了 curl d fi
  • 在 bash 函数中生成后台进程

    我正在编写一个 Bash 函数来启动需要从某个文件夹启动的服务器 但我不希望启动该服务器影响我当前的工作 我写了以下内容 function startsrv pushd cd TRUNK SERVERCOMMAND popd 我的变量都已设
  • 如何替换带引号的多单词字符串作为参数?

    我正在尝试替换包含多个带引号的单词的字符串变量作为命令的参数 因此 给出以下示例脚本 请注意 shebang 中的 x 这会导致输出被记录到 stderr bin bash x myArg hello world echo string i
  • 如何查找出现在括号之间的所有单词?

    我有一个文件 其中包含括号中的一些单词 我想编制一个出现在那里的所有独特单词的列表 例如 This is some text This text has some words in parenthesis Sometimes there a
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • 如何替换每行中出现的所有字符串?

    我想在以下脚本中将所有出现的 用户名 替换为 但它仅替换第一次出现的情况 ls al sed s username 这就是 sed 默认情况下的工作方式吗 提前致谢 你需要g 全局 修饰符 sed s username g
  • envsubst 不能进行就地替换吗?

    我有一个配置文件 其中包含一些 ENV VARIABLE 样式的变量 This is my file It might contain EXAMPLES of text 现在我希望将该变量替换为保存在实际环境变量中的值 所以我正在尝试这个
  • bash双括号问题

    我对 bash 脚本非常陌生 在使用双括号时遇到了问题 我似乎无法让它们在 Ubuntu Server 11 10 中工作 我的下面的脚本位于 if test sh 中 bin bash if 14 14 then echo FOO fi
  • 将所有脚本参数复制到另一个变量

    我需要复制所有脚本参数并将它们传递给另一个脚本 我尝试这样做 args printargs sh args echo printargs sh args 但在这种情况下 如果我使用包含空格的参数调用我的父脚本 例如 script sh ar
  • 在ansible中合并字典

    我目前正在构建一个使用 ansible 安装 PHP 的角色 并且在合并字典时遇到一些困难 我尝试了多种方法来做到这一点 但我无法让它像我想要的那样工作 A vars file my default values key value my
  • IFS 分隔一个字符串,如“Hello”,“World”,“this”,“is,一个无聊”,“line”

    我正在尝试解析 csv 文件 但 IFS 遇到一些问题 该文件包含如下行 Hello World this is a boring line 各列用逗号分隔 因此我尝试使用以下代码分解该行 IFS read r a tempArr lt l
  • 将终端颜色扩展到行尾

    我有一个生成 motd 的 bash 脚本 问题取决于某些终端设置 我不确定颜色是否会延伸到行尾 其他时候则不然 e g v s IIRC 一个只是普通的 gnome 终端 另一个是我的 tmux 术语 所以我的问题是如何才能将其扩展到 8
  • Ansible 无法运行任何命令或 shell

    我在 RPi 上运行任何命令或 shell 时遇到问题 当我使用以下代码时 name Example command ansible builtin command cmd cat etc motd 我收到此错误 Unsupported p
  • 从 bash 脚本运行节点

    很简单 我正在尝试使用 cron 自动运行 nodejs 脚本 但是脚本本身似乎无法运行该文件 我的脚本很简单 usr bin env node node var node assets js update js 但是 在运行此命令时 它返

随机推荐

  • 在 VsCode 中更新笔记本上的环境变量

    我正在使用 VsCode 上的笔记本和 env 文件开发一个 Python 项目 我在尝试刷新笔记本中的环境变量时遇到问题 我找到了一种方法 但非常棘手 我的项目 env 文件包含 MY VAR HELLO ALICE 包含一个单元格的 t
  • 如何测量脚本的执行时间? [复制]

    这个问题在这里已经有答案了 如何测量脚本从开始运行到结束所需的时间 start timing CODE end timing EDIT 2011 年 1 月 这是最佳的可用解决方案 其他解决方案 例如performance now 现在应该
  • Android TimePicker AM/PM 按钮不调用 onTimeChanged

    我在应用程序中实现 TimePicker 时遇到一些问题 该应用程序允许用户在插入数据库记录之前更改数据库记录的时间 问题是 当按下 AM PM 按钮时 不会调用 onTimeChanged View int int 方法 然而 每当我更改
  • Oracle SQL Developer:如何查看引用游标的结果?

    如果我有一个返回查询引用游标的函数 我如何在 SQL Developer 中查看其结果集 Toad 有一个特殊的选项卡 用于查看参考光标的结果 这是我想要找到的功能 SET SERVEROUTPUT ON VARIABLE X REFCUR
  • 为什么 tSQLt 测试在 Visual Studio 测试资源管理器中会通过,而它应该失败?

    我正在编写一些 tSQLt 测试并通过 Visual Studio 的测试资源管理器运行它们tSQLt 测试适配器 https the agilesql club blogs Ed Elliott tSQLt Visual Studio T
  • Heroku Gem 安装后无法使用

    我正在尝试让 heroku 在 Ubuntu 9 10 上运行 I typed sudo gem install heroku 一切正常 但是当我去跑步时 heroku list I get heroku 找不到命令 run 宝石环保看看哪
  • 如何让 git 在 vi​​m 中显示更改,就像 hg 使用 hgeditor 脚本那样?

    Mercurial 的一个有趣的功能是能够查看将在 vim split 中提交的更改 请参阅VIM 中的 DiffsInCommitMessage https www mercurial scm org wiki DiffsInCommit
  • 隐藏折线的正确方法?

    我有一个在地图上显示折线的函数 这部分正在工作 现在我想实现一个隐藏折线的函数 但我找不到我的错误 提前致谢 function cargaMapaCYL mapa varControl var limite null limite new
  • python什么时候删除变量?

    我知道 python 有一个自动垃圾收集器 因此当不再引用变量时 它应该自动删除变量 我的印象是 局部变量 函数内部 不会发生这种情况 def funz z x f z x is a np array and contains a lot
  • Hazelcast 可序列化映射 ClassNotFound 异常

    我正在尝试在一个简单的 Web 应用程序中实现 Hazelcast 我正在尝试将自定义对象存储到我的 Hazelcast Map 中 并在我的 Bid 对象类中实现 Serialized 并进行必要的导入 import java io Se
  • 迅速关闭模态并推送到新的 VC

    我有 tableview 1 表显示一个新的模式窗口 当我按下按钮时 我想关闭模式窗口并推送到 VC 我的代码仅隐藏模式视图 但不进行推送 IBAction func registrationBtn sender AnyObject let
  • Android CardView 删除填充

    我如何摆脱下面布局中的这种奇怪的填充
  • 字符串前后的通配符 - MySql、PSQL

    我需要执行Contains列中的操作 对于包含操作 我们需要在单词前后使用通配符 例如 个性化 查询 gt like sonal 因为这种类型的查询不能使用索引 有什么办法可以提高搜索速度 注意 我使用MySql InnoDB 和PSQL
  • Backbone.js / Marionette.js 中的路由 - 无主题标签、路由列表和子路由器

    我对 Backbone js Marionette js 中的路由有三个问题 1 如何获取我的应用程序路由器已注册的所有路由的列表 例如对于 Express js 在 Node js 中 它将是app routes 我尝试对 Backbon
  • Linux c++:api 与 /proc 文件?

    我正在开发一个应用程序来收集和发送各种系统信息 分区空间 可用空间 笔记本电脑电池信息等 我没有成功地以直接 c api 的形式获取这些信息 尽管它都可以通过 proc 或类似 中的文件获得 所以 我想知道在我的 C 应用程序中读取 解析这
  • 如何获取 bash 中的第 n 个位置参数?

    如何获得nBash 中的第一个位置参数 其中n是变量吗 使用 Bash 的间接功能 bin bash n 3 echo n 运行该文件 ind apple banana cantaloupe dates 生产 cantaloupe Edit
  • Minecraft Forge 1.8 - 加载块纹理

    我刚刚开始学习 Java 同时修改 Minecraft 我看过有关使用 Minecraft Forge API 将块添加到游戏中的教程 但我遇到了问题 不再有 setBlockTextureName 方法 所以我不知道该怎么办 我在游戏中添
  • css 中 & 的作用是什么

    我正在查看一些遗留代码 并在 css 文件中发现如下内容 user modal width auto height auto modal fade in margin top 0 margin left 0 top 83px 这里 的目的是
  • 向后滑动 - InteractivePopGestureRecognizer 不起作用

    我有像这张照片这样的屏幕 HomeViewController 将推送到 maintabbar 并且选项卡栏项目将推送到detailScreen 为什么向后滑动不起作用 我认为这是IOS默认的 请帮我 p s 如果我在 cocoapods
  • 奇怪的 bash 脚本行为 - 生成的命令在复制粘贴时有效,但在脚本中无效

    出于安全原因 我编写了一个简短的 bash 脚本来包装 ansible playbook 命令 这并不复杂 而且大部分脚本在这里都是无关紧要的 最后 我将脚本参数生成的变量中的 ansible 命令放在一起 如下所示 ansible pla