What is the difference between exit and break in a login shell

Issue

I would like to understand why exit behaves differently than break in the following command:

$ set -o pipefail; true | bash -e -lxc 'while true; do <BREAK/EXIT>; done'; echo $?

Is this a bug? Because depending on which one is used, the ~./bash_logout is called throwing an exit code 1 (because clear_console -q fails).

  • With break -> exit code 0
$ set -o pipefail; true | bash -e -lxc 'while true; do break; done'; echo $?
+ '[' '' ']'
+ '[' -d /etc/profile.d ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/01-locale-fix.sh ']'
+ . /etc/profile.d/01-locale-fix.sh
+++ /usr/bin/locale-check C.UTF-8
++ eval
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/apps-bin-path.sh ']'
+ . /etc/profile.d/apps-bin-path.sh
++ snap_bin_path=/snap/bin
++ '[' -n '' ']'
++ '[' -z /usr/share/gnome:/usr/local/share:/usr/share:/var/lib/snapd/desktop ']'
++ snap_xdg_path=/var/lib/snapd/desktop
++ '[' -n '' ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/bash_completion.sh ']'
+ . /etc/profile.d/bash_completion.sh
++ '[' 'x5.1.16(1)-release' '!=' x -a x '!=' x -a x = x ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/cedilla-portuguese.sh ']'
+ . /etc/profile.d/cedilla-portuguese.sh
++ '[' nl = pt -a en '!=' pt ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/debuginfod.sh ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/gnome-session_gnomerc.sh ']'
+ . /etc/profile.d/gnome-session_gnomerc.sh
++ '[' tty = wayland ']'
++ '[' -z /usr/share/gnome:/usr/local/share:/usr/share:/var/lib/snapd/desktop ']'
++ '[' -n '' ']'
++ export XDG_DATA_DIRS
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/im-config_wayland.sh ']'
+ . /etc/profile.d/im-config_wayland.sh
++ '[' tty '!=' wayland ']'
++ return
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/vte-2.91.sh ']'
+ . /etc/profile.d/vte-2.91.sh
++ '[' -n '5.1.16(1)-release' -o -n '' ']'
++ [[ ehxBc == *i* ]]
++ return 0
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/xdg_dirs_desktop_session.sh ']'
+ . /etc/profile.d/xdg_dirs_desktop_session.sh
++ DEFAULT_XDG_CONFIG_DIRS=/etc/xdg
++ DEFAULT_XDG_DATA_DIRS=/usr/local/share/:/usr/share/
++ '[' -n '' ']'
+ unset i
+ '[' -n '5.1.16(1)-release' ']'
+ '[' -f /home/user/.bashrc ']'
+ . /home/user/.bashrc
++ case $- in
++ return
+ '[' -d /home/user/bin ']'
+ '[' -d /home/user/.local/bin ']'
+ true
+ break
0
  • With exit -> exit code 1
$ set -o pipefail; true | bash -e -lxc 'while true; do exit; done'; echo $?
+ '[' '' ']'
+ '[' -d /etc/profile.d ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/01-locale-fix.sh ']'
+ . /etc/profile.d/01-locale-fix.sh
+++ /usr/bin/locale-check C.UTF-8
++ eval
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/apps-bin-path.sh ']'
+ . /etc/profile.d/apps-bin-path.sh
++ snap_bin_path=/snap/bin
++ '[' -n '' ']'
++ '[' -z /usr/share/gnome:/usr/local/share:/usr/share:/var/lib/snapd/desktop ']'
++ snap_xdg_path=/var/lib/snapd/desktop
++ '[' -n '' ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/bash_completion.sh ']'
+ . /etc/profile.d/bash_completion.sh
++ '[' 'x5.1.16(1)-release' '!=' x -a x '!=' x -a x = x ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/cedilla-portuguese.sh ']'
+ . /etc/profile.d/cedilla-portuguese.sh
++ '[' nl = pt -a en '!=' pt ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/debuginfod.sh ']'
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/gnome-session_gnomerc.sh ']'
+ . /etc/profile.d/gnome-session_gnomerc.sh
++ '[' tty = wayland ']'
++ '[' -z /usr/share/gnome:/usr/local/share:/usr/share:/var/lib/snapd/desktop ']'
++ '[' -n '' ']'
++ export XDG_DATA_DIRS
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/im-config_wayland.sh ']'
+ . /etc/profile.d/im-config_wayland.sh
++ '[' tty '!=' wayland ']'
++ return
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/vte-2.91.sh ']'
+ . /etc/profile.d/vte-2.91.sh
++ '[' -n '5.1.16(1)-release' -o -n '' ']'
++ [[ ehxBc == *i* ]]
++ return 0
+ for i in /etc/profile.d/*.sh
+ '[' -r /etc/profile.d/xdg_dirs_desktop_session.sh ']'
+ . /etc/profile.d/xdg_dirs_desktop_session.sh
++ DEFAULT_XDG_CONFIG_DIRS=/etc/xdg
++ DEFAULT_XDG_DATA_DIRS=/usr/local/share/:/usr/share/
++ '[' -n '' ']'
+ unset i
+ '[' -n '5.1.16(1)-release' ']'
+ '[' -f /home/user/.bashrc ']'
+ . /home/user/.bashrc
++ case $- in
++ return
+ '[' -d /home/user/bin ']'
+ '[' -d /home/user/.local/bin ']'
+ true
+ exit
++ '[' 1 = 1 ']'
++ '[' -x /usr/bin/clear_console ']'
++ /usr/bin/clear_console -q
1

Solution

What is the difference between exit and break in a login shell

In this case, the difference is in the execution of .bash_logout script. It is not executed when non-interactive login shell exits… on it’s own. It is executed when non-interactive login shell calls exit explicitly.

When an interactive login shell exits, or a non-interactive login shell executes the exit builtin command, Bash reads and executes commands from the file ~/.bash_logout, if it exists.

Answered By – KamilCuk

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published