Shell file is not invoking from other shell file - linux

I have a.sh and b.sh. I changed shell from bash to ksh. Now it is not invoking b.sh.
a.sh
`#!/bin/ksh
source /home/ec2-user/env
abc_job() {
nohup abc >> $HOME/a.log 2>&1 </dev/null &
}
abc_jbo() >> $HOME/a.log
exit 0`
abc is the binary file of c that invokes b.sh
b.sh
`#!/bin/ksh
echo "completed b.sh job >> $HOME/b.log
exit`

The csh built-in command 'source' has the ksh equivalent '.', in your case:
. /home/ec2-user/env
If execution of /home/ec2-user/env is mandatory you might want to be more defensive and verify that it is present and executable and that it completes successfully.

Related

Cannot get bash variable changed in sourced script after pipe?

I constructed a simple example to illustrate the problem:
caller.sh:
#!/usr/bin/env bash
state="loaded"
source "sh/callee.sh" 2>&1
echo "$state"
callee.sh:
#!/usr/bin/env bash
state="integrated"
when I run caller.sh, it gives the result I want:
integrated
But if I add a pipe after the source command:
caller.sh:
#!/usr/bin/env bash
state="loaded"
source "sh/callee.sh" 2>&1 | cat
echo "$state"
The result becomes:
loaded
Question: How can I preserve/retrieve the changed value of $state in caller.sh?
You can't use a pipe. The source command runs in a subshell that exits after the pipe completes, so state is never set in the shell that calls echo "$state". You can use process substitution to "invert" the pipeline:
state="loaded"
source "sh/callee.sh" 2>&1 > >(cat)
echo "$state"
Now source executes in the same shell.

Csh script won't exit when it was invoked by a Bash script

I wrote a Bash script to invoke a Csh script. After the Csh script finishing, it will not exit, even an "exit" command was appended in the last of the file. The following are scripts:
$ cat test.sh
#!/bin/sh
./test1.csh
$ cat test1.csh
#!/bin/csh
echo "I'am test1.csh"
exit
When I run the "test.sh", the Csh script did not exit.
Using ps -ef | grep test, found that the process is still running, as shown in this screenshot

bash substring working in interpreter mode but not in shell script

When I try to do a substring in bash shell in interpreter mode, I get expected output
bash-4.2$ x="SomeString"
bash-4.2$ echo $x
SomeString
bash-4.2$ y=${x:0:4}
bash-4.2$ echo $y
Some
bash-4.2$
whereas while running the same commands in a shell script, I get an error.
bash-4.2$ cat shell.sh
x="SomeString"
echo $x
y=${x:0:4}
echo $y
bash-4.2$ sh shell.sh
SomeString
shell.sh[3]: y=${x:0:4}: 0403-011 The specified substitution is not valid for this command.
bash-4.2$
The irony is that when I invoke the shell by bash-4.2$ ./shell.sh, it's working.
What's happening here?
I'm on an AIX machine.
Substrings are a bash extension. When you run it as sh, it disables this extension. Use bash shell.sh and it will work.
You should also put #!/bin/bash at the beginning of the script, to ensure that it runs with bash when you invoke it as a command.

Difference between executing a script with 'bash cd.sh' and 'source cd.sh'? [duplicate]

This question already has answers here:
What is the difference between using `sh` and `source`?
(5 answers)
Closed 7 years ago.
Explain the difference between executing a script with bash cd.sh and source cd.sh
cd.sh contains:
#!/bin/sh
cd /tmp
bash execute the script in a child shell that cannot modify the environment of the invoking shell while source executes the script in the current shell:
test.sh
#!/bin/sh
export MY_NAME=chucksmash
echo $MY_NAME
Running test.sh:
chuck#precision:~$ bash test.sh
chucksmash
chuck#precision:~$ echo $MY_NAME
chuck#precision:~$ source test.sh
chucksmash
chuck#precision:~$ echo $MY_NAME
chucksmash
chuck#precision:~$
In bash, commands that look like source script.sh (or . script.sh) run the script in the current shell, regardless of the #! line.
Therefore, if you have a script (named script.sh in this example):
#!/bin/bash
VALUE=1
cd /tmp
This would print nothing (because VALUE is null) and not change your directory (because the commands were executed in another instance of bash):
bash script.sh
echo $VALUE
This would print 1 and change your directory to /tmp:
source script.sh
echo $VALUE
If you instead had this script (named script.py in this example):
#!/usr/bin/env python
print 'Hello, world"
This would give a WEIRD bash error (because it tries to interpret it as a bash script):
source shell.py
This would *also *give a WEIRD bash error (because it tries to interpret it as a bash script):
bash shell.py
This would print Hello, world:
./shell.py # assuming the execute bit it set

Shell scripting shell inside shell

I would like to connect to different shells (csh, ksh etc.,) and execute command inside each switched shell.
Following is the sample program which reflects my intention:
#!/bin/bash
echo $SHELL
csh
echo $SHELL
exit
ksh
echo $SHELL
exit
Since, i am not well versed with Shell scripting need a pointer on how to achieve this. Any help would be much appreciated.
If you want to execute only one single command, you can use the -c option
csh -c 'echo $SHELL'
ksh -c 'echo $SHELL'
If you want to execute several commands, or even a whole script in a child-shell, you can use the here-document feature of bash and use the -s (read commands from stdin) on the child shells:
#!/bin/bash
echo "this is bash"
csh -s <<- EOF
echo "here go the commands for csh"
echo "and another one..."
EOF
echo "this is bash again"
ksh -s <<- EOF
echo "and now, we're in ksh"
EOF
Note that you can't easily check the shell you are in by echo $SHELL, because the parent shell expands this variable to the text /././bash. If you want to be sure that the child shell works, you should check if a shell-specific syntax is working or not.
It is possible to use the command line options provided by each shell to run a snippet of code.
For example, for bash use the -c option:
bash -c $code
bash -c 'echo hello'
zsh and fish also use the -c option.
Other shells will state the options they use in their man pages.
You need to use the -c command line option if you want to pass commands on bash startup:
#!/bin/bash
# We are in bash already ...
echo $SHELL
csh -c 'echo $SHELL'
ksh -c 'echo $SHELL'
You can pass arbitrary complex scripts to a shell, using the -c option, as in
sh -c 'echo This is the Bourne shell.'
You will save you a lot of headaches related to quotes and variable expansion if you wrap the call in a function reading the script on stdin as:
execute_with_ksh()
{
local script
script=$(cat)
ksh -c "${script}"
}
prepare_complicated_script()
{
# Write shell script on stdout,
# for instance by cat-ting a here-document.
cat <<'EOF'
echo ${SHELL}
EOF
}
prepare_complicated_script | execute_with_ksh
The advantage of this method is that it easy to insert a tee in the pipe or to break the pipe to control the script being passed to the shell.
If you want to execute the script on a remote host through ssh you should consider encode your script in base 64 to transmit it safely to the remote shell.

Resources