0

I'm using source to insert generated variables into a string from a file in order to execute that string from a bash script.

I've echoed the generated string to compare to one that works from the command line and I can't seem to see any difference, but the bash command fails as it seems the supplied parameters are getting mixed up somewhere in the middle.

I've escaped double quotes around the ice_name string, so it looks identical to the one that works when I echo it

Do I need to escape other characters?

It seems to be getting mixed up BEFORE the -ice_name parameter

This is the command

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

Not sure if it you need the file beng sourced, but just in case here it is

#!/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

Script that processes config file and generates stream command

#!/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
dbmitch
  • 5,361
  • 4
  • 24
  • 38
  • What is the command you use to generate the command after you source the file? I suspect you are falling victim to literal quotes; `echo "foo"` and `bar='"foo"'; echo $bar` are not identical. – chepner Jul 08 '16 at 19:46
  • Just using $streamcmd - no echo. Or do you want to see script that does all the merges and concatenates – dbmitch Jul 08 '16 at 20:24
  • Added script to original question – dbmitch Jul 08 '16 at 20:30

1 Answers1

2

Embedding quotes in a string does not escape the wrapped characters; they are just literal characters in the value. You need to use arrays for this:

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"
chepner
  • 497,756
  • 71
  • 530
  • 681
  • I'll give this a try - I was told in a separate conversation asking about the source command that I could just run the command by executing the one variable directly. This looks **radically** different. I just assumed it was right when it looked good on the screen - and the error indicated it was trying to process the command, but failing on the parameters – dbmitch Jul 08 '16 at 20:39
  • You were told wrong. See [I'm trying to put a command in a variable, but the complex cases always fail!](http://mywiki.wooledge.org/BashFAQ/050) – chepner Jul 08 '16 at 20:50
  • Gawdam! Genius!. Thanks so much - wish I had asked earlier. Must have spent 2 hours last night over and over again – dbmitch Jul 08 '16 at 21:12
  • Was the main issue embedded quotes - or would I have had to use this method if I didn't have a parameter with spaces in it? I think I should rename my question title to more accurately represent the problem – dbmitch Jul 08 '16 at 21:15
  • 1
    In this case, you *might* have gotten away with it; if the expanded command is free of special glob characters like `*` or `?`, only has whitespace intended to separate arguments, and doesn't use any shell syntax like `|`, `>`, or `&&`, then the expansion of `$test_cmd` should result in a valid *simple* command. In general, though, variable should only be used to hold data, not executable code. For everything else, use arrays and shell functions. – chepner Jul 08 '16 at 21:18
  • In nearly every case I see where someone tries to do this, it appears to be an attempt to store the command as a single string so that it can be logged. – chepner Jul 08 '16 at 21:19
  • Going to ask another question that expands on this one - re piping into avconv - will reference this one – dbmitch Jul 08 '16 at 21:35
  • Not sure if you're a sh expert as well as bash - I just posted a question about this code failing when using `/bin/sh` - it doesn't like the line `stream_parameters=(-ice_name "$icecast_show" -f mp3)` saying syntax error - and shellcheck message is `In POSIX sh, arrays are undefined`. I think I'm forced to use sh, when I call a script thru AT command – dbmitch Jul 14 '16 at 05:28
  • http://stackoverflow.com/questions/38365845/syntax-error-in-sh-built-and-working-for-bash – dbmitch Jul 14 '16 at 05:28