Run/execute concatenated variable as command - bash

word2018 FILE_2018 > FILE_2018.out &
this works OK for me in bin/bash, terminal, konsole, BASH
I have an text-file script in #!/bin/bash, where I run this variable CMD and it works in CSH, but not in BASH.
CMD="word${year} ${FILE_version.txt} > ${FILE_version.out} &"
word2018 - system alias defined/sourced from other location
word - static name
2018 - variable (can be any number 2015, 2022,....)
FILE_version - variable (can be - FILE_2015, FILE_2022,...)
csh -c "$CMD" ...works OK
bash -c "$CMD" ...NOT working, command word2018 not found
any advice, help? I would appreciate very well

Just call $CMD
testABC(){
echo "arg: $1"
}
alias_name=test
#....system alias
var1=ABC
var2=123
CMD="${alias_name}${var1} ${var2}"
echo CMD: $CMD
$CMD
result:
CMD: testABC 123
arg: 123

Related

access modifiers in bash

Say I have a bash script and I want some variables to appear when sourced and others to only be accessible from within the script (both functions and variables). What's the convention to achieve this?
Let's say test.sh is your bash script.
What you can do is extract all the common items and put them in common.sh which can be sourced by other scripts.
The BASH_SOURCE array helps you here:
Consider this script, source.sh
#!/bin/bash
if [[ ${BASH_SOURCE[0]} == "$0" ]]; then
# this code is run when the script is _executed_
foo=bar
privFunc() { echo "running as a script"; }
main() {
privFunc
publicFunc
}
fi
# this code is run when script is executed or sourced
answer=42
publicFunc() { echo "Hello, world!"; }
echo "$0 - ${BASH_SOURCE[0]}"
[[ ${BASH_SOURCE[0]} == "$0" ]] && main
Running it:
$ bash source.sh
source.sh - source.sh
running as a script
Hello, world!
Sourcing it:
$ source source.sh
bash - source.sh
$ declare -p answer
declare -- answer="42"
$ declare -p foo
bash: declare: foo: not found
$ publicFunc
Hello, world!
$ privFunc
bash: privFunc: command not found
$ main
bash: main: command not found

SSH running sh script that works locally but not remotely

I am trying to run a script that will be called by some other software to run some parameters to get out objective values.
The script run.sh is as follows:
#!/bin/bash
set -e
ssh id#somehost '
/path/to/folder/solver arg1 arg2 arg3
res=$(</path/to/folder/res_data.txt)
echo "Final Result:"
echo "1 $res"
'
Running this file results in the following:
$ sh run.sh
OpenNN Exception: NeuralNetwork class.
void load(const std::string&) method.
Cannot load XML file ../data/neural_network.xml.
Final Result:
1 -285361 3.22136
Connection to somehost closed.
The Final Result above is from a previous output
If I run a similar script without the ssh
set -e
/path/to/folder/solver arg1 arg2 arg3
res=$(</path/to/folder/res_data.txt)
echo "Final Result:"
echo "1 $res"
Results in
$ sh run.sh 7 26 100
Final Result:
1 -285361 3.22136
$ sh run.sh 7 26 150
Final Result:
1 -421429 5.16397
Does anyone have any idea how to fix this?
Based on the comments above the solution of the error I was getting,
#!/bin/bash
set -e
ssh id#somehost '
cd /path/to/folder/
./solver '$1' '$2' '$3'
res=$(<./res_data.txt)
echo "Final Result:"
echo "1 $res"
'
I was simple enough just to add cd /path/to/folder/ and run the script from the folder it seems to work, in addition I also fixed the issue with the arguments rather than ./solver $1 $2 $3, having ./solver '$arg1' '$arg2' '$arg3' as the way to pass the inputted arguments to run on the solver.
The following output is from the corrected file above
$ sh run.sh 7 26 100
Final Result:
1 -285361 3.22136
$sh run.sh 7 26 150
Final Result:
1 -421429 5.16397

How does quote in a cmd string work and how does the quote interact with eval for bash script?

I tried the commands in a bash script.
#!/bin/bash
cmd='pgrep -d " " -f "python test.py"'
$cmd
cmd2=(pgrep -d \" \" -f \"python test.py\")
${cmd2[#]}
Both don't work returning pgrep: only one pattern can be provided as you expect. however both work with eval command like the below.
eval $cmd
eval ${cmd2[#]}
The errors seem from using quote(") but I don't have any idea why and how eval command interacts with the quote in here though I have tried to understand with the below description.
DESCRIPTION
The eval utility shall construct a command by concatenating arguments together, separating
each with a <space>. The constructed command shall be read and executed by the shell.
EXAMPLES
foo=10 x=foo
y='$'$x
echo $y
$fooeval y='$'$x
echo $y
10
Could you give me the explanation?
Take a look at the output here and see if it helps.
showArgs(){
test $# = 0 && return
echo "arg:" "$1"
shift
showArgs "$#"
}
cmd='pgrep -d " " -f "python test.py"'
echo Without eval ---------
showArgs $cmd
echo With eval --------
eval showArgs $cmd
Also try set -x to enable debug output.

Syntax for inlining return value of call

While you can inline output of a program as parameters
$ echo $(ls)
cpp python bash
or as a temporary file
$ echo <(ls)
/proc/self/fd/63
I wonder how you can inline the return value with a similar syntax, so that it echoes the return-value of ls that it works like this:
$ ls
$ echo $?
0
ls_retval=$(ls >/dev/null 2>&1; echo "$?")
If you want to encapsulate that:
# define a function...
retval_of() { "$#" >/dev/null 2>&1; echo "$?"; }
# and use it
ls_retval=$(retval_of ls)
As for "with a similar syntax", though -- the shell has the syntax that it has; there doesn't exist "retval substitution" (as of bash 4.4, or POSIX sh as standardized in POSIX Issue 7).

Get command used to start a script

How to get the command previously used to start a shell script?
for example:
nohup /script_name.sh &
Inside the script itself, how to check if "nohup" has been used?
Thanks.
You want to use the $_ parameter in your script.
Example: shell.sh
#!/bin/bash
echo $_;
user#server [~]# sh shell.sh
/usr/bin/sh
user#server [~]#
Additionally:
If you want to get rid of that full path - /usr/bin/sh - utilize basename command.
#!/bin/bash
echo `basename $_`;
user#server [~]# sh shell.sh
sh
user#server [~]#
well that depends on the script in question.There're many ways to execute a script like:
./<scriptname> #chmod 700 <scriptname> should be done before executing this script
bash <scriptname> # provided bash is used for executing the script.
or if you just want to get the name of script2 in script1, then use sed or awk for parsing the script1 with regular expression => /script2/.
Try this:
cat <script1> | awk '{ if( $0 ~ /^[^#].* \/scriptname.sh/ ){ print $1}}'
#codebaus thanks, doing something like this works but using strace definitely not.
#!/bin/bash
# echo $_
# echo $0
if grep "sh" $_ >/dev/null ; then
exit 1
fi ;
echo "string" ;
I believe you want to run this?:
#!/bin/bash
# echo $_
# echo $0
if grep "sh" $_ 2> /dev/null ; then
exit 1
fi ;
echo "string";
user#server [~]# sh shell.sh
Binary file /usr/bin/sh matches
user#server [~]#
Not sure what you are trying to accomplish in the end game. But $_ should give you what you need based on your initial question.
Additionally:
As I did not answer your strace comment, apologies. Based on the previous code above.
strace sh shell.sh
wait4(-1, Binary file /usr/bin/strace matches
[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 874
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD (Child exited) # 0 (0) ---

Resources