Update PS1 during wwctl image shell to include working directory

Optionally, use `WW_PS1` to construct the prompt.

- Closes: #1245

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-02-10 16:45:50 -07:00
committed by Christian Goll
parent 1ca16456fe
commit 609dc286ef
3 changed files with 29 additions and 6 deletions

View File

@@ -25,6 +25,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 - syncuser overlay skips duplicate users and groups in passwd and group databases. #829
- `wwctl image syncuser --write` is true by default. #1736 - `wwctl image syncuser --write` is true by default. #1736
- Update syncuser documentation. #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 ### Fixed

View File

@@ -20,8 +20,6 @@ import (
"github.com/warewulf/warewulf/internal/pkg/wwlog" "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) { func CobraRunE(cmd *cobra.Command, args []string) (err error) {
if os.Getpid() != 1 { if os.Getpid() != 1 {
return fmt.Errorf("PID is not 1: %d", os.Getpid()) 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 { if err != nil {
return fmt.Errorf("failed to mount: %w", err) 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 == "" { if len(lowerObjects) != 0 && nodename == "" {
options := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", options := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s",
path.Join(runDir, "lower"), imagePath, path.Join(runDir, "work")) 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 { if err != nil {
return fmt.Errorf("couldn't create overlay for node render overlay: %s", err) 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 == "" { if !image.IsWriteAble(imageName) && nodename == "" {
wwlog.Verbose("mounting %s ro", imagePath) 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, "") err = syscall.Mount(imagePath, imagePath, "", syscall.MS_BIND, "")
if err != nil { if err != nil {
return fmt.Errorf("failed to prepare bind mount: %w", err) return fmt.Errorf("failed to prepare bind mount: %w", err)
@@ -172,7 +170,15 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
return fmt.Errorf("failed to mount /run: %w", err) return fmt.Errorf("failed to mount /run: %w", err)
} }
os.Setenv("PS1", ps1Str) 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))
os.Setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin") os.Setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin")
os.Setenv("HISTFILE", "/dev/null") os.Setenv("HISTFILE", "/dev/null")

View File

@@ -291,6 +291,21 @@ 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 will be an additional check to confirm if the users are in sync as
described in `Syncuser`_ section. 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:/$
Excluding Files from an Image Excluding Files from an Image
----------------------------- -----------------------------