diff --git a/CHANGELOG.md b/CHANGELOG.md index ac3688eb..b57c4bae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Added `UniqueField` template function. #829 - Added `wwctl image build --syncuser`. #1321 - Added support for a DNSSEARCH netdev tag in network configuration overlays. #1256 +- Added `WW_HISTFILE` to control shell history location during `wwctl image shell`. #1732 ### Changed @@ -25,6 +26,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - syncuser overlay skips duplicate users and groups in passwd and group databases. #829 - `wwctl image syncuser --write` is true by default. #1736 - Update syncuser documentation. #1736 +- Update PS1 during `wwctl image shell` to include working directory by default, + and to include `PS1` from the environment if present. #1245 ### Fixed diff --git a/internal/app/wwctl/image/exec/child/main.go b/internal/app/wwctl/image/exec/child/main.go index f3b5a2e7..c3fe9d8f 100644 --- a/internal/app/wwctl/image/exec/child/main.go +++ b/internal/app/wwctl/image/exec/child/main.go @@ -20,8 +20,6 @@ import ( "github.com/warewulf/warewulf/internal/pkg/wwlog" ) -const exitEval = `$(VALU="$?" ; if [ $VALU == 0 ]; then echo write; else echo discard; fi)` - func CobraRunE(cmd *cobra.Command, args []string) (err error) { if os.Getpid() != 1 { return fmt.Errorf("PID is not 1: %d", os.Getpid()) @@ -78,7 +76,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if err != nil { return fmt.Errorf("failed to mount: %w", err) } - ps1Str := fmt.Sprintf("[%s|%s] Warewulf> ", imageName, exitEval) + ps1Prefix := fmt.Sprintf(`[warewulf:%s]`, imageName) if len(lowerObjects) != 0 && nodename == "" { options := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", path.Join(runDir, "lower"), imagePath, path.Join(runDir, "work")) @@ -114,11 +112,11 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if err != nil { return fmt.Errorf("couldn't create overlay for node render overlay: %s", err) } - ps1Str = fmt.Sprintf("[%s|ro|%s] Warewulf> ", imageName, nodename) + ps1Prefix = fmt.Sprintf(`warewulf:%s(ro)] `, imageName) } if !image.IsWriteAble(imageName) && nodename == "" { wwlog.Verbose("mounting %s ro", imagePath) - ps1Str = fmt.Sprintf("[%s|ro] Warewulf> ", imageName) + ps1Prefix = fmt.Sprintf(`warewulf:%s(ro)] `, imageName) err = syscall.Mount(imagePath, imagePath, "", syscall.MS_BIND, "") if err != nil { return fmt.Errorf("failed to prepare bind mount: %w", err) @@ -172,9 +170,25 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { return fmt.Errorf("failed to mount /run: %w", err) } - os.Setenv("PS1", ps1Str) os.Setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin") - os.Setenv("HISTFILE", "/dev/null") + + var ps1Base string + if v, ok := os.LookupEnv("WW_PS1"); ok { + ps1Base = v + } else { + ps1Base = `\w\$ ` + os.Setenv("WW_PS1", ps1Base) + } + os.Setenv("PS1", fmt.Sprintf("%s %s", ps1Prefix, ps1Base)) + + var histfile string + if v, ok := os.LookupEnv("WW_HISTFILE"); ok { + histfile = v + } else { + histfile = "/dev/null" + os.Setenv("WW_HISTFILE", histfile) + } + os.Setenv("HISTFILE", histfile) wwlog.Debug("Exec: %s %s", args[1], args[1:]) return syscall.Exec(args[1], args[1:], os.Environ()) diff --git a/userdocs/contents/images.rst b/userdocs/contents/images.rst index 253b2b58..9af651a9 100644 --- a/userdocs/contents/images.rst +++ b/userdocs/contents/images.rst @@ -291,6 +291,31 @@ If the files ``/etc/passwd`` or ``/etc/group`` were updated, there will be an additional check to confirm if the users are in sync as described in `Syncuser`_ section. +Specifying a prompt +------------------- + +Warewulf sets a custom prompt during a ``wwctl image shell`` session. This +prompt may be customized using the ``WW_PS1`` variable, which is used to +construct the final ``PS1`` variable for the shell. + +.. code-block:: + + # wwctl image shell rockylinux-9 + [warewulf:rockylinux-9] /# + + # env WW_PS1="\u@\h:\w\$ " wwctl image shell rockylinux-9 + [warewulf:rockylinux-9] root@rocky:/$ + +Shell history +------------- + +By default, Warewulf image shell sessions don't retain history; but you can +specify a history file by specifing ``WW_HISTFILE``. Note that this file is +stored within the image; you may want to exclude it when the image is built. +(See :ref:`exclude`.) + +.. _exclude: + Excluding Files from an Image -----------------------------