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?
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
.