【问题标题】:Bash script fails when running command with embedded quotes (source parameters)运行带有嵌入式引号(源参数)的命令时,Bash 脚本失败
【发布时间】:2023-03-03 15:59:01
【问题描述】:

我正在使用source 将生成的变量插入文件中的字符串中,以便从 bash 脚本中执行该字符串。

我已经回显了生成的字符串以与从命令行运行的字符串进行比较,我似乎看不出有任何区别,但是 bash 命令失败,因为提供的参数似乎在中间的某个地方混淆了.

我已经在 ice_name 字符串周围转义了双引号,所以它看起来与我回显它时起作用的那个相同

我需要转义其他字符吗?

-ice_name 参数之前似乎混淆了

这是命令

avconv -re -i test.mp3 -c:a libmp3lame -content_type audio/mpeg -b:a 128k -legacy_icecast 1 
-ice_name "Raspi Test Stream of MP3" -f mp3 
icecast://:mypwd@icecast.servername.com/my/mount/point/url

不确定您是否需要该文件,但以防万一

#!/bin/bash
#
# stream.cfg
#
# WiFi Settings
#
wifi_name=mywifi
wifi_password=mywifipwd
#
# Icecast Server Settings
#
icecast_server=icecast.server.com
icecast_port=443
icecast_mount_url=/user/mountpt/url
icecast_show="RPi Demo Show - autostart"
icecast_description="Test of Stream from RPi USB Audio to Spreaker"
icecast_user=""
# Source password
icecast_password=sourcepwd
#
# avconv setting for Raspbian Jessie Lite
# may not need if you're using a self compiled ffmpeg version
#
icecast_legacy=1
#
# Stream Settings - probably not safer to go higher unless great internet connection
#
stream_bitrate=128k

处理配置文件并生成流命令的脚本

#!/bin/bash
#
# autostart-settings.sh
#
# Load in config file settings

CONFIG_FILE=~/autostart/autostart-settings.cfg

# Check if file exists
echo "does file exist"
if [ ! -f "$CONFIG_FILE" ]; then
    echo "Config File: $(CONFIG_FILE) does not exist"
    exit 1
else
    # process settings
    echo "running source on $CONFIG_FILE"
    source "$CONFIG_FILE"
fi

start_cmd="avconv -re -i /home/pi/test.mp3 -c:a libmp3lame -content_type audio/mpeg -b:a $stream_bitrate -legacy_icecast $icecast_legacy"

stream_parameters="-ice_name \"$icecast_show\" -f mp3"

icecast_setup="icecast://$icecast_user:$icecast_password@$icecast_server:$icecast_port$icecast_mount_url"

test_cmd="$start_cmd $stream_parameters $icecast_setup"
echo "Testing command: $test_cmd"

# Run command
$test_cmd

【问题讨论】:

  • 获取文件后用于生成命令的命令是什么?我怀疑您正在成为文字引用的受害者; echo "foo"bar='"foo"'; echo $bar 不相同。
  • 只使用 $streamcmd - 没有回声。还是您想查看执行所有合并和连接的脚本
  • 将脚本添加到原始问题

标签: bash shell raspberry-pi sh avconv


【解决方案1】:

在字符串中嵌入引号不会转义被换行的字符;它们只是值中的文字字符。您需要为此使用数组:

cmd=avconv
args=(-re -i /home/pi/test.mp3 -c:a libmp3lame -content_type audio/mpeg -b:a "$stream_bitrate" -legacy_icecast "$icecast_legacy")

stream_parameters=(-ice_name "$icecast_show" -f mp3)

icecast_setup="icecast://$icecast_user:$icecast_password@$icecast_server:$icecast_port$icecast_mount_url"

test_cmd="$start_cmd $stream_parameters $icecast_setup"
echo "Testing command: $cmd ${args} ${stream_parameters[@]} $icecast_setup"

# Run command
"$cmd" "${args[@]}" "${stream_parameters[@]}" "$icecast_setup"

【讨论】:

  • 我会试一试 - 我在另一次询问源命令的对话中被告知,我可以通过直接执行一个变量来运行该命令。这看起来根本不同。我只是假设它在屏幕上看起来不错时是正确的 - 错误表明它正在尝试处理命令,但参数失败
  • 牛当!天才!。非常感谢 - 希望我早点问过。昨晚一定是一遍又一遍地度过了 2 个小时
  • 主要问题是嵌入引号 - 或者如果我没有包含空格的参数,我是否必须使用此方法?我想我应该重命名我的问题标题以更准确地代表问题
  • 在这种情况下,您可能侥幸逃脱;如果扩展命令没有像*? 这样的特殊全局字符,只有用于分隔参数的空格,并且不使用像|>&& 这样的任何shell 语法,那么$test_cmd 的扩展应该会产生一个有效的 simple 命令。但是,一般来说,变量应该只用于保存数据,而不是可执行代码。对于其他一切,请使用数组和 shell 函数。
猜你喜欢
  • 2019-05-28
  • 1970-01-01
  • 2021-05-02
  • 2016-01-22
  • 2019-02-08
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多