paul paul - 6 months ago 20
Bash Question

Execute function defined in config file

I´m implememnting a generic bash script where I receive as parameter from my config file a function. Then I just want to execute that function.

My config file contains.

downloadFunction="curl -s 'https://foo.com/foo.jar' -o '/bla.jar'"


Then in the main bash file I try this two thnigs

# load config
. ${script_dir}/configs/${config}/config || exit 1

exec bash -c "${downloadFunction}"//This works.
echo "Downloaded"


Doing that works, but after the execution the script stop and "Downloaded" it´s never showed. But still the file is downloaded

If I try using $() like

$("${downloadFunction}")


The it´s telling me

línea 42: curl -s 'https://foo.com/foo.jar' -o '/bla.jar'': No existe el fichero o el directorio


Any idea how to execute a function passed to my main bash as configuration parameter?

Regards

Answer

This is not a function definition:

downloadFunction="curl -s 'https://foo.com/foo.jar' -o '/bla.jar'"

This is a function definition:

downloadFunction() { curl -s 'https://foo.com/foo.jar' -o '/bla.jar'; }

...and you absolutely can define it in that way in a config file being sourced.


If you fix your function definition to actually be a function, you can call it as so:

downloadFunction

If you intend to pass a string full of code to be interpreted in the current interpreter, and able to contain arbitrary content (redirections, flow-control, etc), use eval to evaluate it:

# do this only if the content of the variable has been human-audited and is known
# ...not to be malicious; shell injection vulnerabilities can occur otherwise.
eval "$downloadFunction"

If rather than an arbitrary function or a string you intend to pass a single command to be evaluated literally (with no redirections or other shell directives), use an array variable instead, and expand it appropriately:

# do this only in special cases -- ie. building up the command incrementally
downloadCommand=( curl -s 'https://foo.com/foo.jar' -o 'bla.jar' )
"${downloadCommand[@]}"

For best practices, see BashFAQ #50.

Comments