mirror of
https://github.com/containers/podman.git
synced 2025-08-01 04:42:20 +08:00
Merge pull request #11513 from Luap99/unshare
podman unshare keep exit code
This commit is contained in:
@ -2,6 +2,7 @@ package system
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||
@ -50,5 +51,23 @@ func unshare(cmd *cobra.Command, args []string) error {
|
||||
args = []string{shell}
|
||||
}
|
||||
|
||||
return registry.ContainerEngine().Unshare(registry.Context(), args, unshareOptions)
|
||||
err := registry.ContainerEngine().Unshare(registry.Context(), args, unshareOptions)
|
||||
if err != nil {
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
// the user command inside the unshare env has failed
|
||||
// we set the exit code, do not return the error to the user
|
||||
// otherwise "exit status X" will be printed
|
||||
registry.SetExitCode(exitError.ExitCode())
|
||||
return nil
|
||||
}
|
||||
// cmd.Run() can return fs.ErrNotExist, fs.ErrPermission or exec.ErrNotFound
|
||||
// follow podman run/exec standard with the exit codes
|
||||
if errors.Is(err, os.ErrNotExist) || errors.Is(err, exec.ErrNotFound) {
|
||||
registry.SetExitCode(127)
|
||||
} else if errors.Is(err, os.ErrPermission) {
|
||||
registry.SetExitCode(126)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -37,6 +37,35 @@ connect to a rootless container via IP address (CNI networking). This is otherwi
|
||||
not possible from the host network namespace.
|
||||
_Note: Using this option with more than one unshare session can have unexpected results._
|
||||
|
||||
## Exit Codes
|
||||
|
||||
The exit code from `podman unshare` gives information about why the container
|
||||
failed to run or why it exited. When `podman unshare` commands exit with a non-zero code,
|
||||
the exit codes follow the `chroot` standard, see below:
|
||||
|
||||
**125** The error is with podman **_itself_**
|
||||
|
||||
$ podman unshare --foo; echo $?
|
||||
Error: unknown flag: --foo
|
||||
125
|
||||
|
||||
**126** Executing a _contained command_ and the _command_ cannot be invoked
|
||||
|
||||
$ podman unshare /etc; echo $?
|
||||
Error: fork/exec /etc: permission denied
|
||||
126
|
||||
|
||||
**127** Executing a _contained command_ and the _command_ cannot be found
|
||||
|
||||
$ podman run busybox foo; echo $?
|
||||
Error: fork/exec /usr/bin/bogus: no such file or directory
|
||||
127
|
||||
|
||||
**Exit code** _contained command_ exit code
|
||||
|
||||
$ podman run busybox /bin/sh -c 'exit 3'; echo $?
|
||||
3
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
```
|
||||
|
@ -47,8 +47,7 @@ var _ = Describe("Podman unshare", func() {
|
||||
session := podmanTest.Podman([]string{"unshare", "readlink", "/proc/self/ns/user"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(0))
|
||||
ok, _ := session.GrepString(userNS)
|
||||
Expect(ok).To(BeFalse())
|
||||
Expect(session.OutputToString()).ToNot(ContainSubstring(userNS))
|
||||
})
|
||||
|
||||
It("podman unshare --rootles-cni", func() {
|
||||
@ -57,4 +56,36 @@ var _ = Describe("Podman unshare", func() {
|
||||
Expect(session).Should(Exit(0))
|
||||
Expect(session.OutputToString()).To(ContainSubstring("tap0"))
|
||||
})
|
||||
|
||||
It("podman unshare exit codes", func() {
|
||||
session := podmanTest.Podman([]string{"unshare", "false"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(1))
|
||||
Expect(session.OutputToString()).Should(Equal(""))
|
||||
Expect(session.ErrorToString()).Should(Equal(""))
|
||||
|
||||
session = podmanTest.Podman([]string{"unshare", "/usr/bin/bogus"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(127))
|
||||
Expect(session.OutputToString()).Should(Equal(""))
|
||||
Expect(session.ErrorToString()).Should(ContainSubstring("no such file or directory"))
|
||||
|
||||
session = podmanTest.Podman([]string{"unshare", "bogus"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(127))
|
||||
Expect(session.OutputToString()).Should(Equal(""))
|
||||
Expect(session.ErrorToString()).Should(ContainSubstring("executable file not found in $PATH"))
|
||||
|
||||
session = podmanTest.Podman([]string{"unshare", "/usr"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(126))
|
||||
Expect(session.OutputToString()).Should(Equal(""))
|
||||
Expect(session.ErrorToString()).Should(ContainSubstring("permission denied"))
|
||||
|
||||
session = podmanTest.Podman([]string{"unshare", "--bogus"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(125))
|
||||
Expect(session.OutputToString()).Should(Equal(""))
|
||||
Expect(session.ErrorToString()).Should(ContainSubstring("unknown flag: --bogus"))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user