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
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.
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
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.
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
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.