16

first.sh:

#! /bin/ksh
echo "prova"
. ./second.sh
echo "ho lanciato il secondo"
. ./third.sh
echo "ho lanciato il terzo"

second.sh:

echo "sono nel secondo script"
dosomething1
exit $?

If second.sh detects an error and exits with status -9, first.sh exits always. How I can do avoid exiting from the first shell if the child shell exits?

I can't edit second.sh.

2
  • Here you are using the . command, which sources another file in the current shell. There is no child shell or subshell involved. Did you mean to execute second.sh and third.sh instead of sourcing them?
    – Celada
    Jul 22 '15 at 15:25
  • yes.. i must write execute instead of . ./ ? i want ignore "exit $?" inside second.sh.. is possible without edit second.sh? Jul 22 '15 at 15:26
19

What you're doing here is including second.sh and third.sh as sub-scripts running in the same process, which is called “sourcing” in shell programming. . ./second.sh is basically equivalent to including the text of second.sh at that point. The exit command exits the process, it doesn't matter whether you call it in the original script or in a sourced script.

If all you want to do is run the commands in second.sh and third.sh and they don't need to access or modify variables and functions from the original script, call these scripts as child processes.

#! /bin/ksh
echo "prova"
./second.sh
echo "ho lanciato il secondo"
./third.sh
echo "ho lanciato il terzo"

If you need the other scripts to access variables and functions from the original script, but not modify them, then call these scripts in subshells. Subshells are separate processes, so exit exits only them.

#! /bin/ksh
echo "prova"
(. ./second.sh)
echo "ho lanciato il secondo"
(. ./third.sh)
echo "ho lanciato il terzo"

If you need to use variables or functions defined in second.sh and third.sh in the parent script, then you'll need to keep sourcing them.

The return builtin exits only the sourced script and not the whole process — that's one of the few differences between including another script with the . command and including its text in the parent script. If the sourced scripts only call exit at the toplevel, as opposed to inside functions, then you can change exit into return. You can do that without modifying the script by using an alias.

#! /bin/ksh
echo "prova"
alias exit=return
. ./second.sh
echo "ho lanciato il secondo"
. ./third.sh
unalias exit
echo "ho lanciato il terzo"

If exit is also called inside functions, I don't think there's a non-cumbersome way. A cumbersome way is to set an exit trap and put your code there.

#!/bin/ksh
do_first () {
  echo "prova"
  trap "after_second" EXIT
  . ./second.sh
  after_second
}
after_second () {
  echo "ho lanciato il secondo"
  trap "after_third" EXIT
  . ./third.sh
  after_third
}
after_third () {
  trap - EXIT
  echo "ho lanciato il terzo"
}
do_first
1
  • It is for this reason that I've stopped using '.' to source files into a script, and try to exclusively use 'source' instead. IMO that should be considered a bash 'best practice', since it makes it much clearer what your code is doing. Feb 6 '17 at 18:06
7

Instead of sourcing the second and third shell, just run them as you would any other command. The exit code can be stored and used if you need, like so:

#! /bin/ksh
echo "prova"

# execute and capture stdout ... output of second is not seen ...
OUTPUT1=$(./second.sh)

# find out exit status of second.sh
STATUS1=$?

# ... until now
echo $OUTPUT1

# do something based on the result
if [ $STATUS1 -eq 0 ]; then 
  echo "second.sh ran successfully"
else 
  echo "second.sh crapped out"
fi

# and so on...
3
  • STATUS1=$? will catch result of previously issued echo command, which is independent of result of ./second.sh.
    – Cromax
    Mar 30 '17 at 10:05
  • @Cromax you're completely right. Answer has been edited. Mar 30 '17 at 18:53
  • Thank you. I used this and adapted it for my menu of menus bash setup.
    – Kim Stacks
    Jun 30 at 10:04
0

Try it this way (remove first . on calling second.sh):

first.sh:

#! /bin/ksh
echo "prova"
./second.sh
echo "ho lanciato il secondo"
./third.sh
echo "ho lanciato il terzo"

second.sh:

echo "sono nel secondo script"
dosomething1
exit $?

This is because . is shortcode for source which cause the second script to be included as a part of first one.

0

script1.sh

  1 PWD="/scratch/currdir"
  2 echo "Hello from scrpt 1"
  3
  4 sh $PWD/script2.sh # We will exit in script2.sh and see if line 6 gets printed
  5
  6 echo "From script 1: After scrpt2 call"
  7 exit 0

script2.sh

  1 echo "Hello from script 2"
  2
  3 exit 1
  4 echo "This should not get printed"

Output:

-bash-4.1$ sh script1.sh
Hello from scrpt 1
Hello from script 2
From script 1: After scrpt2 call

(Note: Although we exited script2 (line number 3 with exit 1), but still in script1.sh the line no 6 gets executed post calling script2.sh

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.