0

I wrote a lot of bash scripts that should work with the current bash session, because I often used fg, jobs, etc.

I always starts my scripts with . script.sh but one of my friends startet it with ./script.sh and got error that fg "couldn't be executed". Is it possible to force a . script.sh or anything else what I can do to prevent errors? Such as cancel the whole script and print an error with echo or something else.

Edit: I think bashtraps have problems when executing sourced, is there any way to use fg, jobs and bashtraps in one script?

  • 1
    possible duplicate of [How to detect if a script is being sourced](http://stackoverflow.com/questions/2683279/how-to-detect-if-a-script-is-being-sourced) – Cyrus May 25 '15 at 15:21
  • @Cyrus: that's not a dup (though there probably is one). The issue is not whether the script is sourced but whether it is interactive. Detecting whether it is sourced or not is not sufficient here (could be sourced from a non-interactive shell). – Mat May 25 '15 at 15:26

3 Answers3

4

Looks like you're trying to determine if a script is being run interactively or not. The bash manual says that you can determine this with the following test:

#! /bin/bash

case "$-" in
*i*)  echo interactive ;;
*)    echo non-interactive ;;
esac

sleep 2 &
fg

If you run this with ./foo.sh, you'll see "non-interactive" printed and an error for the fg built-in. If you source it with . foo.sh or source foo.sh you won't get that error (assuming you're running those from an interactive shell, obviously).

For your use-case, you can exit with an error message in the non-interactive mode.

Mat
  • 202,337
  • 40
  • 393
  • 406
1

If job control is all you need, you can make it work both ways with #!/bin/bash -i:

#!/bin/bash -i
sleep 1 &
fg

This script works the same whether you . myscript or ./myscript.

PS: You should really adopt your friend's way of executing scripts. It's more robust and most people write their scripts to work that way (e.g. assuming exit will just exit the script).

that other guy
  • 116,971
  • 11
  • 170
  • 194
0

There are a couple of simple tricks to remind people to use source (or .) to run your script: First, remove execute permission from it (chmod -x script.sh), so running it with ./script.sh will give a permission error. Second, replace the normal shebang (first line) with something like this:

#!/bin/echo please run this with the command: source

This will make the script print something like "please run this with the command: source ./script.sh" (and not run the actual script) if someone does manage to execute it.

Note that neither of these helps if someone runs the script with bash script.sh.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • 1
    Shebangs aren't guaranteed to pass through more than two arguments. (See http://www.in-ulm.de/~mascheck/various/shebang/ for gruesome details on portability of shebang lines). – Charles Duffy May 25 '15 at 19:52
  • @CharlesDuffy: Yikes, I didn't realize shebang handling was that inconsistent. I guess if you're on an OS that only supports one argument, you'd need to do something like `#!/bin/echo please_run_this_with_the_command:source`. And if you're on 4.0BSD, 4.1BSD, or 386BSD-0.1p2.3, this trick won't work at all. – Gordon Davisson May 26 '15 at 01:10