How to specify zeroeth argument - bash

I'm writing a bash script that starts the tcsh interpreter as a login shell and has it execute my_command. The tcsh man page says that there are two ways to start a login shell. The first is to use /bin/tcsh -l with no other arguments. Not an option, because I need the shell to execute my_command. The second is to specify a dash (-) as the zeroeth argument.
Now the bash exec command with the -l option does exactly this, and in fact the following works perfectly:
#!/bin/bash
exec -l /bin/tcsh -c my_command
Except... I can't use exec because I need the script to come back and do some other things afterwards! So how can I specify - as the zeroeth argument to /bin/tcsh without using exec?

You can enclose the exec command into a sub-shell of your script.
#!/bin/bash
(exec -l /bin/tcsh -c my_command)
# ... whatever else you need to do after the command is done

You can write a wrapper (w.sh) script that contains:
#!/bin/bash
exec -l /bin/tcsh -c my_command
and execute w.sh in your main script.

Related

Bash pass argument to --init-file script

I'm running a shell script using bash --init-file script.sh that runs some commands, then leaves an interactive session open. How can I pass arguments to this init file from the process that runs the initial bash command? bash --init-file 'script.sh arg' doesn't work.
Interestingly, if the script contains echo "$# $*", passing an argument as I did above causes it to print nothing, while not passing an argument prints '0'.
Create a file with the content:
#!/bin/bash
script.sh arg
Pass that file to bash: bash --init-file thatfile
I'd like the arg to come from the command that runs bash with the
Create a file from the command line and pass it:
arg="$1"
cat >thatfile <<EOF
$(declare -p arg)
script.sh \"\$arg\"
EOF
bash --init-file thatfile
You might be interested in researching what is a process substitution in bash.

How to execute a command in a different shell?

I have a bash script that opens up a shell called salome shell and it should execute a command called as_run in that shell. The thing is that after entering the salome shell it doesn't execute the command until I exit the salome shell. This is the code that i got:
#!/bin/bash
cd /opt/salome/appli_V2018.0.1_public
./salome shell
eval "as_run /home/students/gbroilo/Desktop/Script/Template_1_2/exportSalome"
What should I do in order to execute the command in the salome shell?
Might be this is what you want:
# call salome shell with commands in a specified script file
cd /opt/salome/appli_V2018.0.1_public
./salome shell <"/home/students/gbroilo/Desktop/Script/Template_1_2/exportSalome"
Or might be this is what you want:
# pipe a command as_run... to salome shell
cd /opt/salome/appli_V2018.0.1_public
echo "as_run /home/students/gbroilo/Desktop/Script/Template_1_2/exportSalome" | ./salome shell
Anyway, you have to read the salome guide about how salome shell call it's script.
Most shells implement a way to pass the commands as parameters, e.g.
dash -c 'x=1 ; echo $x'
You'll need to consult your shell's manual to see if it's possible.
You can also try sending the commands to the standard input of the shell:
echo 'set x = 1 ; echo $x' | tcsh
Using a HERE doc might be a bit more readable in case of complex commands:
tcsh << 'TCSH'
set x = 1
echo $x
TCSH

How can I redirect stdout and stderr with variant?

Normally, we use
sh script.sh 1>t.log 2>t.err
to redirect log.
How can I use variant to log:
string="1>t.log 2>t.err"
sh script.sh $string
You need to use 'eval' shell builtin for this purpose. As per man page of bash command:
eval [arg ...]
The args are read and concatenated together into a single command. This command is then read and exe‐
cuted by the shell, and its exit status is returned as the value of eval. If there are no args, or
only null arguments, eval returns 0.
Run your command like below:
eval sh script.sh $string
However, do you really need to run script.sh through sh command? If you instead put sh interpreter line (using #!/bin/sh as the first line in your shell script) in your script itself and give it execute permission, that would let you access return code of ls command. Below is an example of using sh and not using sh. Notice the difference in exit codes.
Note: I had only one file try.sh in my current directory. So ls command was bound to exit with return code 2.
$ ls try1.sh try1.sh.backup 1>out.txt 2>err.txt
$ echo $?
2
$ eval sh ls try1.sh try1.sh.backup 1>out.txt 2>err.txt
$ echo $?
127
In the second case, the exit code is of sh shell. In first case, the exit code is of ls command. You need to make cautious choice depending on your needs.
I figure out one way but it's ugly:
echo script.sh $string | sh
I think you can just put the name into a string variable
and then use data redirection
file_name="file1"
outfile="$file_name"".log"
errorfile="$file_name"".err"
sh script.sh 1> $outfile 2> $errorfile

Proper syntax for bash exec

I am trying to do the following:
if ps aux | grep "[t]ransporter_pulldown.py" > /dev/null
then
echo "Script is already running. Skipping"
else
exec "sudo STAGE=production $DIR/transporter_pulldown.py" # this line errors
fi
$ sudo STAGE=production $DIR/transporter_pulldown.py works on the command line, but in a bash script it gives me:
./transporter_pulldown.sh: line 9:
exec: /Users/david/Desktop/Avails/scripts/STAGE=production
/Users/david/Desktop/Avails/scripts/transporter_pulldown.py:
cannot execute: No such file or directory
What would be the correct syntax here?
sudo isn't a command interpreter thus its trying to execute the first argument as a command.
Instead try this:
exec sudo bash -c "STAGE=production $DIR/transporter_pulldown.py"
This creates uses a new bash processes to interpret the variables and execute your python script. Also note that $DIR will be interpreted by the shell you're typing in rather than the shell that is being executed. To force it to be interpreted in the new bash process use single quotes.

Passing arguments to /bin/bash via a bash script

I am writing a bash script that takes a number of command line arguments (possibly including spaces) and passes all of them to a program (/bin/some_program) via a login shell. The login shell that is called from the bash script will depend on the user's login shell. Let's suppose the user uses /bin/bash as their login shell in this example... but it might be /bin/tcsh or anything else.
If I know how many arguments will be passed to some_program, I can put the following lines in my bash script:
#!/bin/bash
# ... (some lines where we determine that the user's login shell is bash) ...
/bin/bash --login -c "/bin/some_program \"$1\" \"$2\""
and then call the above script as follows:
my_script "this is too" cool
With the above example I can confirm that some_program receives two arguments, "this is too" and "cool".
My question is... what if I don't know how many arguments will be passed? I'd like to pass all the arguments that were sent to my_script along to some_program. The problem is I can't figure out how to do this. Here are some things that don't work:
/bin/bash --login -c "/bin/some_program $#" # --> 3 arguments: "this","is","too"
/bin/bash --login -c /bin/some_program "$#" # --> passes no arguments
Quoting the bash manual for -c:
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
Works for me:
$ cat x.sh
#!/bin/bash
/bin/bash --login -c 'echo 1:$1 2:$2 3:$3' echo "$#"
$ ./x.sh "foo bar" "baz" "argh blargh quargh"
1:foo bar 2:baz 3:argh blargh quargh
I don't know how you arrived at the "passes no arguments" conclusion, maybe you missed the $0 bit?
Avoid embedding variables into other scripts, pass them on as arguments instead. In this case:
bash --login -c 'some_program "$#"' some_program "$#"
The first argument after -c '...' is taken as $0, so I just put in some_program there.
On a side note, it's an odd requirement to require a login shell. Doesn't the user log in?

Resources