Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I know that set -e is my friend in order to exit on error. But what to do if the script is sourced, e.g. a function is executed from console? I dont want to get the console closed on error, I just want to stop the script and display the error-message.

Do I need to check the $? of each command by hand to make that possible ?

Here an example-script myScript.sh to show the problem:

#!/bin/sh
set -e

copySomeStuff()
{
    source="$1"
    dest="$2"
    cp -rt "$source" "$dest"
    return 0
}

installStuff()
{
    dest="$1"
    copySomeStuff dir1 "$dest"
    copySomeStuff dir2 "$dest"
    copySomeStuff nonExistingDirectory "$dest"
}

The script is used like that:

$ source myScript.sh
$ installStuff

This will just close down the console. The error displayed by cp is lost.

share|improve this question
1  
Are you sure it would close down the console? I tried to run the script as you described and it terminates the whole things throwing cp error and exiting with 1 exit code. – ddnomad yesterday
1  
@ddnomad The set -e sets the errexit option in the shell. When calling the function, the cp fails and the shell exits for me. – Kusalananda yesterday
1  
If you source that it will ignore the #! and will apply set -e to the calling shell, so will apply to all subsequent commands. – richard yesterday
    
Double quote your user input. Don't use () when calling shell functions. – Kusalananda yesterday
1  
Ok, done, thanks – Alex yesterday
up vote 4 down vote accepted

I would recommend having one script that you run as a sub-shell, possibly sourcing a file to read in function definitions. Let that script set the errexit shell option for itself.

When you use source from the command line, "the script" is effectively your interactive shell. Exiting means terminating the shell session. There are possibly ways around this, but the best option, if you wanted to set errexit for a session, would be to simply have:

#!/bin/bash

set -o errexit

source file_with_functions
do_things_using_functions

Additional benefit: Will not pollute the interactive session with functions.

share|improve this answer
    
@Alex Maybe you could be a bit heavy-handed and just refuse to do anything if the script is sourced? Or do you need to allow for both sourcing and running as a sub-shell? – Kusalananda yesterday
    
@Alex When you source a file with commands from the prompt, "the script" is your current interactive shell session. Exiting means ending the shell session. You will need to use another mechanism to act on errors, such as cp ... && do_other_thing. – Kusalananda yesterday
    
@Alex, I've updated my answer. – Kusalananda yesterday
    
Ok, that does the job, thanks! It's a more readable solution and probably should be preferred in most cases. However for my special use-case it would result in 6 files, since I provide different services there, currently implemented as functions, and I would like to stick to 1 file for other reason. – Alex yesterday

If you source that it will ignore the #! and will apply set -e to the calling shell, so will apply to all subsequent commands.

you could force a sub-shell:

copySomeStuff()
{
    (
        set -e
        source="$1"
        dest="$2"
        cp -r "$source" "$dest"
        return 0
    )
}

Also for safety:

  • Do not use all caps variable name, as likely to collide with environment names. (we had a question last week about why a script did not work, it had a variable PATH)

  • Use quotes.

  • Always use -t or -T option for cp, mv, ln. e.g.

    • cp -t destination_directory source_files …
    • cp -T source_file destination_file

    note that -t and -T are Gnu extensions, and not available on some other Unixes, so for portability you can in place of the -t option do:

    • cp source_files … destination_directory/

    I do not know of an alternate safe form for -T

share|improve this answer
2  
Just a note about cp -t, it's a GNU extension not available on BSD systems. If GNU coreutils is installed, GNU cp may be available as gcp. – Kusalananda yesterday
    
set -e in the sub-shell works great, thanks ! As well thanks for the safety-hints. – Alex yesterday

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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