Structure of error messages in bash

6

Bash error messages sometimes have a -bash: or bash: prefix, sometimes none.

Consider these error messages from Ubuntu 14.04.5 Trusty Tahr with bash 4.3.11(1)

$ type encabulator
-bash: type: encabulator: not found

$ encabulator
encabulator: command not found

$ bash -c encabulator
bash: encabulator: command not found

In another question, someone reports seeing a message

-bash: fetch: command not found.

Which doesn't match the pattern expected when "fetch" is simply a program that has not been installed.


After comments below, I tried using bash 3.2.25(1) on Centos 5.7 - which behaves slightly differently

$ type encabulator
-bash: type: encabulator: not found

$ encabulator
-bash: encabulator: command not found

$ bash -c encabulator
bash: encabulator: command not found

So I guess the message from the other question means exactly what I first thought, before my test with bash 4.3.11 confused me.

It still leaves open the question of whether the bash maintainers intended to apply some consistent system to the structure of these text messages?


When exactly does bash prefix error messages with -bash: and when with bash: (what does the leading hyphen indicate?)

I couldn't find answers using a simple search in man bash but maybe there's a section that provides an explanation?

RedGrittyBrick

Posted 2018-06-27T10:17:14.127

Reputation: 70 632

I'd say it's the opposite – your 2nd example doesn't match any bash version I have here. – user1686 – 2018-06-27T10:21:10.117

bash in my Kubuntu behaves like in the question; the same in Debian. In Raspbian, however, the pattern is like in the other question. The versions are 4.3.48, 4.4.12 and 4.3.30 respectively. – Kamil Maciorowski – 2018-06-27T10:37:50.597

After reading above comments, I have updated the question with bash version number and with test results from a different system. – RedGrittyBrick – 2018-06-27T14:00:57.347

Answers

5

When exactly does bash prefix error messages with -bash: and when with bash:

The prefix, if printed, is usually the name with which bash was started, aka argv[0] (usually available in $0).

$ bash -c 'type foo; echo $0'
bash: line 0: type: foo: not found
bash
$ ARGV0=bar bash -c 'type foo; echo $0'
bar: line 0: type: foo: not found
bar
$ ARGV0='¯\(°_o)/¯' bash -c 'type foo; echo $0'
¯\(°_o)/¯: line 0: type: foo: not found
¯\(°_o)/¯

(This uses zsh's special ARGV0 variable to set argv[0] of a command to whatever we want.)

For starting bash as a login shell, whatever starts bash may prefix argv[0] with -, or use the -l option. See Invoking Bash:

A login shell is one whose first character of argument zero is ‘-’, or one invoked with the --login option.

So, for example,

$ ARGV0=-bash bash -c 'echo -n $0:;shopt -q login_shell && echo login || echo not login'
-bash:login
$ bash -c 'echo -n $0:;shopt -q login_shell && echo login || echo not login'
bash:not login

SSH, sudo (with -i), the TTY login command, etc. usually use the leading - method to start a login shell. So, if you logged in via any of these, you're likely to see -bash (or -zsh, or -tcsh, or whatever you login shell is with - in front of it). If you started bash via a terminal emulator, those usually run non-login shells and you'd see bash.


what does the leading hyphen indicate?

That it's probably a login shell, which may be an useful point in debugging. In particular, PATH is often set from files sourced by login shells (/etc/profile, ~/.profile, ~/.bash_profile, etc. - see Bash Startup Files for more). For a command-not-found error, this would be particularly important, since PATH is how commands are found. It gives you useful information as to which files should be checked for modifying PATH.

muru

Posted 2018-06-27T10:17:14.127

Reputation: 975

Thanks, +1, I have amended my answer accordingly (crediting you) to remove incorrect/misleading information. I've not deleted my answer because I think it is useful to know about variation in behaviour between bash versions and that omission of "bash:" prefix is probably a bug -- or at least so far has no discernible intended meaning. – RedGrittyBrick – 2018-07-02T09:28:48.040

@RedGrittyBrick the omission of bash can be reasoned about like this: the guideline is to print the program name and error message. So when running a built-in (type, printf), the program is bash, and bash's name is printed (and all built-ins for which I could force an error do so). But when executing an external command fails (which may not be simply because there's no such file), the program couldn't even be started, so bash prints a message for it, so omitting the name. Probably worth filing a bug to see if that's intended, though. – muru – 2018-07-02T09:41:08.083

2

When exactly does bash prefix error messages with -bash: and when with bash:

It is arbitrary.

what does the leading hyphen indicate?

Nothing useful. See muru's answer which points out that the hyphen indicates that the error message is being reported by a login shell.


Bash Manual

The GNU manual for Bash mentions a shell option

gnu_errfmt

    If set, shell error messages are written in the standard GNU error message format.

I tried setting it, the results in the question were unchanged.

GNU Coding Standards

The GNU Coding Standards seem mainly concerned with error messages from compilers (i.e. gcc?) however, section 4.4 says

4.4 Formatting Error Messages

...

... like this:

    program: message

when there is no relevant source file.  

GNU libc

GNU's libc manual gives this example for producing error messages.

fprintf (stderr, "%s: Couldn't open file %s; %s\n",
               program_invocation_short_name, name, strerror (errno));
      exit (EXIT_FAILURE);

From the lack of detail in the above documentation and from the variation seen in the question, I deduce that there is no specific meaning intended by the presence or absence of the bash: prefix.

RedGrittyBrick

Posted 2018-06-27T10:17:14.127

Reputation: 70 632

0

To add to muru’s answer, the canonical way of setting argv[0] for sh -c or bash -c is to provide a string after the command string.  So, for example,

$ sh -c '"$@"' mush date +'%B %e'
July  7

$ sh -c '"$@"' mush fig  +'%B %e'
mush: fig: command not found

$ sh -c '"$@"' mush type fig
mush: line 0: type: fig: not found

Related:

G-Man Says 'Reinstate Monica'

Posted 2018-06-27T10:17:14.127

Reputation: 6 509