7

I am using startx to start the graphical environment. I have a very simple .xinitrc which I will add things to as I set up the environment, but for now it is as follows:

catwm & # Just a basic window manager, for testing.

xterm

The reason I background the WM and foreground terminal and not the other way around as often is done, is because I would like to be able to come back to the virtual text console after typing exit in xterm. This appears to work as described.

The problem is that the PS1 variable that currently is set to my preference in /etc/profile.d/user.sh (which is sourced from /etc/profile supplied by distro), does not appear to propagate to the environment of the xterm mentioned above. The relevant process tree is as follows:

\_ -bash
    \_ xinit /home/user/.xinitrc -- /etc/X11/xinit/xserverrc :0 -auth /tmp/serverauth.ggJna3I0vx
        \_ /usr/bin/X -nolisten tcp :0 -auth /tmp/serverauth.ggJna3I0vx vt1
        \_ sh /home/user/.xinitrc
            \_ /home/user/catwm
            \_ xterm
                \_ bash

The shell started by xterm appears to be interactive, the shell executing .xinitrc however is not. I am ok with both, the assumptions about interactivity seem to be perfectly valid, but now I have a non-interactive shell that spawns an interactive shell indirectly, and the interactive shell has no chance to automatically inherit the prompt, because the prompt was unset or otherwise made unavailable higher up the process tree. How do I go about getting my prompt back?

2
  • 1
    I retracted my answer. You might want to update your question though, explaining what worked for you and what didn't.
    – slhck
    Oct 21, 2013 at 10:42
  • I have edited the question to better reflect state of things as they now stand. Oct 21, 2013 at 11:04

1 Answer 1

5

Commands env and export list only variables which are exported. $PS1 is usually not exported. Try echo $PS1 in your shell to see actual value of $PS1.

Non-interactive shells usually do not have $PS1. Non-interactive bash explicitly unsets $PS1.1 You can check if bash is interactive by echo $-. If the output contains i then it is interactive. You can explicitly start interactive shell by using the option on the command line: bash -i. Shell started with -c is not interactive.

The /etc/profile script is read for a login shell. You can start the shell as a login shell by: bash -l.

With bash shell the scripts /etc/bash.bashrc and ~/.bashrc are usually used to set $PS1. Those scripts are sourced when interactive non-login shell is started. It is your case in the xterm. See Setting the PS? Strings Permanently

Possible solutions

  • Start the shell inside xterm as a login shell: bash -l. Check if /etc/profile and ~/.profile do not contain code which should be executed only after login. Maybe slight modifications of the scripts will be needed.
  • Use a different shell. For example dash does not unset $PS1. You can use such a shell just as the non-interactive shell which will run the scripts up to xterm.
  • Give up the strict POSIX compliance and use the bash-standard place for setting $PS1: /etc/bash.bashrc or ~/.bashrc.
  • Give up the strict POSIX compliance and source your own startup script like: bash --rcfile <(echo "PS1=$PS1save") -i
  • Start the intermediate shells from startx till xterm as interactive shells (bash -i). Unfortunately this can have some side-effect and I would not do this.
5
  • I am specifically avoiding to set PS1 in .bashrc or /etc/bash.bashrc (which is executed as well), to retain POSIX shell compatibility. These do not set or unset PS1. PS1 is set in /etc/profile.d/user.sh, which is sourced by /etc/profile. Indeed, this file is only executed for login shells, however I do export PS1 from /etc/profile.d/user.sh exactly because I want propagation of my preferred value down the process tree. So it shouldn't matter which subshells are login and/or interactive ones then, should it? Oct 21, 2013 at 11:32
  • It seems that bash removes the PS1 variable. What exactly do you want to achieve by "POSIX shell compatibility"? Do you want to be able to replace bash by a different POSIX-compliant shell and retain the same functionality? Based on my tests bash removes PS1 when it is started as non-interactive. I think of two simple solutions: 1. start the shell as a login shell with the -l option (attention for actions in the startup scripts which should be started only at login) 2. start the intermediate shells as interactive with the -i option. Oct 21, 2013 at 12:00
  • I try to follow interfaces and specifications, not implementations - hence POSIX compatibility. That's important (to me). I already have one login shell - the one started by /usr/bin/login. I understand that a non-interactive shell doesn't need prompt, but unsetting a variable is too much - I need the prompt in an interactive shell (spawned and used by xterm) later on. What am I doing wrong? I guess most people set their prompt in .bashrc which is sourced by bash anyway, and so the prompt survives. I try to avoid .bashrc however. Oct 22, 2013 at 12:12
  • @amn: I have added various possible solutions to the reply. Oct 22, 2013 at 16:46
  • 1
    Thanks for the elaborate answer. Now I'm curious why bash unsets PS1. There doesn't seem to be any benefit at the cost of broken scripts and user confusion. I'm currently using guix, which wraps every executable in a bash script, thereby always eating PS1.
    – BlackShift
    Aug 24, 2020 at 10:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .