Search code examples
shellcommand-promptsingularity-container

How to change the default prompt in a singularity container


I am creating a Singularity image and I want to have a custom bash prompt, just like I can set a bash prompt as a normal user by setting the variable PS1 in my ~/.bash_profile.

But, unfortunately, Singularity does something to enforce its own prompt that looks like this: Singularity>. This is not a very helpful prompt.

I tried to set PS1 in the definition file like in this example:

# File prompt-test1.def
Bootstrap: shub
From: alpine:latest
%environment
export PS1="[my-container]\w\$ "

I built and ran that image, but to no avail:

sudo singularity build prompt-test.sif prompt-test.def
singularity shell prompt-test.sif
# shows Singularity>

Using the env command in the shell, I noticed that PROMPT_COMMAND is set:

echo $PROMPT_COMMAND
# PS1="Singularity> "; unset PROMPT_COMMAND

... so I tried to change that:

# File prompt-test2.def
Bootstrap: shub
From: alpine:latest
%environment
export PROMPT_COMMAND='PS1="[my-container]\w\$ "; unset PROMPT_COMMAND'

... but the prompt remains unchanged! But now, PROMPT_COMMAND inside the container looks like

echo $PROMPT_COMMAND
# PS1="[my-container]\w\$ "; unset PROMPT_COMMAND; PROMPT_COMMAND="${PROMPT_COMMAND%%; PROMPT_COMMAND=*}";PS1="Singularity> "

edited to replace with better info: The problem lies in the order in which the files in /.singularity.d/env are sourced. The user-defined environment variables are set in 01-base.sh, but in 99-base.sh there is the line

PS1="Singularity> "

... which overwrites my prompt! Also, the approach using PROMPT_COMMAND is thwarted because of some code in /.singularity.d/actions/shell or .../run.

A workaround would be for the user to use an own .profile. But that does not work if the user's home directory is bound to the home inside the container, because the .profile inside and outside of the container is the same then. Also, I don't want user intervention just to change a prompt.

How can I get my prompt?


Solution

  • By default, the shells run by singularity explicitly don't load any profile or rc files. The prompt, annoying as it is, is there to remind you that you are in an image, not the host OS.

    If you want to override that anyway, you need to add an additional file to /.singularity.d/env that will be run after everything else. e.g.,

    Bootstrap: docker
    From: alpine:latest
    
    %post -c /bin/bash
        CUSTOM_ENV=/.singularity.d/env/99-zz_custom_env.sh
        cat >$CUSTOM_ENV <<EOF
    #!/bin/bash
    PS1="[my_container]\w \$"
    EOF
        chmod 755 $CUSTOM_ENV
    

    Adding -c /bin/bash after %post tells singularity to use /bin/bash instead of the default /bin/sh, necessary for the multiline cat step afterwards.

    EDIT: older versions of singularity used a shebang in the first line for specifying an alternate shell, but has changed to -c /path/to/shell.