4

So I know there are plenty of answers on stack overflow for ignoring errors in a bash script. None of them seem to work for the source command though.

I have tried the tried and true source ../bin/activate || true

I have tried setting set -e before running the command

I have tried source ../bin/activate 2>&1 /dev/null

I have tried setting set +e before running the command. This did not work either.

but on every run-through of this code, I receive

run.01: line 12: ../bin/activate: No such file or directory

The context for this problem is that I'm creating a simple bash script that runs some python code. The user is instructed for how to create a specific virtual environment and this line will automatically activate it if they set it up correctly, otherwise, this should ignore failing to activate running and continue running the commands in whatever environment is currently activated.

# Try virtual environment

source ../bin/activate || true

## Run.

code="../src-01/driver.v01.py"

## --------------------
graphInputFile="undirected_graph_01.inp"
graphType="undirected"
srcColId="0"
desColId="1"
degreeFind="2"
outFile="count.undirected.num.nodes.out"

python $code  -inpGraphFile $graphInputFile  -graphFormat $graphType  -colSrcId $srcColId -colDesId $desColId  -degreeFind $degreeFind  -output_file $outFile

The python command should execute regardless of whether or not the source ../bin/activate command succeeds or not. I'm a little a loss for why none of these solutions are working and am currently under the assumption that source might do something different than a normal command given the circumstances.

EDIT:

I added the shebang #!/bin/bash -x to my file as requested but this did not do anything.

I this is my exact terminal output when I run this script.

Lucas-Macbook:test-01 lucasmachi$ sh run.01
run.01: line 14: ../bin/activate: No such file or directory
Lucas-Macbook:test-01 lucasmachi$ 

Where run.01 is the name of the bash script.

Also to clarify, the code I showed is not censored. that is the entire script (except now with the mentioned shebang at the top.)

Vapidant
  • 2,532
  • 2
  • 12
  • 26
  • What actual problem are you trying to solve? The script will display an error message and continue even without the `|| true`, unless you are running under `set -e`. – tripleee Jan 15 '20 at 18:16
  • That's a massive collection of unquoted variables. It's probably harmless here, but a seriously unpleasant odor. Read [When to wrap quotes around a shell variable?](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable) – tripleee Jan 15 '20 at 18:17
  • @triplee the problem is that it does not continue to run. It displays that error then stops running. – Vapidant Jan 15 '20 at 18:53
  • So you still have `set -e` active? – tripleee Jan 15 '20 at 18:55
  • Change your shebang to `#!/bin/bash -x` to show a debug log, and then post it unmodified and unabbreviated. If it contains information you don't want to share, please edit the *script* to remove it and rerun, instead of editing the output – that other guy Jan 15 '20 at 18:58
  • @tripleee actually the script should continue to run with `|| true` appended to the failing command even if `set -e` has been set. At least according to the answers in [this SO question](https://stackoverflow.com/questions/3517162/how-to-undo-the-effect-of-set-e-which-makes-bash-exit-immediately-if-any-comm) – Jiri Valenta Jan 15 '20 at 20:10
  • @Vapidant it is a bit crude, but you could try running `set +e` before your `source` command, and then `set -e` afterwards again... Assuming you need to set it in the first place - if the script you pasted is all that there is, I'd say you probably don't need to bother with `set -e` at all, since you're basically just executing another python script with it and nothing else. – Jiri Valenta Jan 15 '20 at 20:14
  • @JiriValenta actually I tried that too. No luck. – Vapidant Jan 15 '20 at 21:04
  • @thatotherguy unless I don't understand how to shebang (I put what you said as the first line in my shell script) then this didn't work. I put the exact terminal output in my edit. – Vapidant Jan 15 '20 at 21:18
  • 1
    Don't use `sh run.01`, now that you've set the shebang use `./run.01` instead. If you get a permission error, make `run.01` executable with `chmod +x ./run.01` then use `./run.01` again. `sh` is a link to your default shell, but if it's `bash` (and I assume others too) it will run your script in POSIX-compliant mode when called as `sh`, which won't help you unless you're trying to make your script portable, and might explain some of your troubles – Aaron Jan 15 '20 at 21:20
  • I believe `source` is a `bash`ism, the equivalent POSIX command being `.`. Might be enough to explain your problems, although I don't get why you run into this particular error nor why your redirection attempt didn't at least conceal the error – Aaron Jan 15 '20 at 21:23
  • 1
    @Vapidant your edit just revealed that you're running the script with `sh` instead of `bash` - this can be the reason for this behavior. Personally I've seen similar oddities when using `sh` instead of `bash` and wasted quite some time debugging it, followed by banging my head against the keyboard when I realized what the mistake was. Try running it as `bash run01.sh` or put the shebang as the first line of the script as suggested here (you can omit the `-x` if you don't want to see the debug output), do `chmod +x run01.sh` and then run it as `./run01.sh` (as @Aaron suggested already) – Jiri Valenta Jan 15 '20 at 21:29
  • 1
    Maybe see also https://stackoverflow.com/a/42666651/874188 which has a section about this FAQ. – tripleee Jan 16 '20 at 04:49

3 Answers3

5

You could add a validation in your code to check whether the file exists before sourcing it :

[[ -f "../bin/activate" ]] && source ../bin/activate

Using the -f flag before a path will return true if the path file exists, and false if it doesn't.

The one liner syntax for bash if statements is as follow :

[[ Condition that returns true or false ]] && Exec if true 
Dexirian
  • 515
  • 3
  • 15
5

This is a bug in Bash versions before 4.0 (macOS is stuck on 3.2).

Given this script:

#!/bin/bash
set -e
echo "Running $BASH_VERSION"
source "does not exist" || true
echo "Continuing"

Running on macOS will say:

macos$ ./myscript
Running 3.2.57(1)-release
./myscript: line 3: does not exist: No such file or directory

While on a modern system with an updated bash version, you get the expected behavior:

debian$ ./myscript
Running 5.0.11(1)-release
./myscript: line 3: does not exist: No such file or directory
Continuing

If you need to support macOS and Bash 3.2, run set +e first to disable errexit, and optionally re-enable it afterwards.

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

I ran into this issue with gitlab pipelines. None of the above worked for me, but combining the answers did:

[[ -f "${ENVIRONMENT}_test" ]] && source "${ENVIRONMENT}_test" || true

This gets me to where I need to go, hopefully it will help someone in the future.

Cognitiaclaeves
  • 808
  • 10
  • 16