Add a run command

This makes 'toolbox enter' similar to 'toolbox run $SHELL'.

The 'run' command is meant to spawn arbitrary binaries present inside
the toolbox container. Therefore it doesn't make sense for it to fall
back to /bin/bash, like it does for 'enter' if $SHELL is absent.

It's expected that users might use 'run' to create ad-hoc *.desktop
files. That's why it neither offers to create nor falls back to an
existing container like 'enter' does, because such interactions can't
happen when used in a *.desktop file. It's also a more advanced command
that new users are less likely to be interested in. Hence, this
shouldn't affect usability.

Some changes by Debarshi Ray.

https://github.com/debarshiray/toolbox/pull/76
This commit is contained in:
Toni Schmidbauer 2019-03-08 07:42:29 +01:00 committed by Debarshi Ray
parent 0e38e7d0b3
commit 2da4cc4634
4 changed files with 132 additions and 11 deletions

View file

@ -13,7 +13,7 @@ __toolbox() {
local MIN_VERSION=29 local MIN_VERSION=29
local RAWHIDE_VERSION=31 local RAWHIDE_VERSION=31
local verbose_commands="create enter list" local verbose_commands="create enter list run"
local commands="$verbose_commands rm rmi" local commands="$verbose_commands rm rmi"
declare -A options declare -A options
@ -21,7 +21,8 @@ __toolbox() {
[enter]="--container --release" \ [enter]="--container --release" \
[list]="--containers --images" \ [list]="--containers --images" \
[rm]="--all --force" \ [rm]="--all --force" \
[rmi]="--all --force") [rmi]="--all --force" \
[run]="--container --release")
_init_completion -s || return _init_completion -s || return

View file

@ -11,6 +11,7 @@ manuals = [
'toolbox-list.1', 'toolbox-list.1',
'toolbox-rm.1', 'toolbox-rm.1',
'toolbox-rmi.1', 'toolbox-rmi.1',
'toolbox-run.1',
] ]
foreach manual: manuals foreach manual: manuals

60
doc/toolbox-run.1.md Normal file
View file

@ -0,0 +1,60 @@
% toolbox-run(1)
## NAME
toolbox\-run - Run a command in an existing toolbox container
## SYNOPSIS
**toolbox run** [*--container NAME* | *-c NAME*]
[*--release RELEASE* | *-r RELEASE*] [*COMMAND*]
## DESCRIPTION
Runs a command inside an existing toolbox container. The container should have
been created using the `toolbox create` command.
A toolbox container is an OCI container. Therefore, `toolbox run` is analogous
to a `podman start` followed by a `podman exec`.
On Fedora the toolbox containers are tagged with the version of the OS that
corresponds to the content inside them. Their names are prefixed with the name
of the base image and suffixed with the current user name.
## OPTIONS ##
The following options are understood:
**--container** NAME, **-c** NAME
Run command inside a toolbox container with the given NAME. This is
useful when there are multiple toolbox containers created from the
same base image, or entirely customized containers created from
custom-built base images.
**--release** RELEASE, **-r** RELEASE
Run command inside a toolbox container for a different operating
system RELEASE than the host.
## EXAMPLES
### Run ls inside a toolbox container using the default image matching the host OS
```
$ toolbox run ls -la
```
### Run emacs inside a toolbox container using the default image for Fedora 30
```
$ toolbox run --release f30 emacs
```
### Run uptime inside a custom toolbox container using a custom image
```
$ toolbox run --container foo uptime
```
## SEE ALSO
`buildah(1)`, `podman(1)`, `podman-exec(1)`, `podman-start(1)`

77
toolbox
View file

@ -988,10 +988,20 @@ create()
enter() enter()
{
run true false "$SHELL" -l
}
run()
( (
fallback_to_bash="$1"
pedantic="$2"
program="$3"
shift 3
create_toolbox_container=false create_toolbox_container=false
prompt_for_create=true prompt_for_create=true
shell_to_exec=/bin/bash
echo "$base_toolbox_command: checking if container $toolbox_container exists" >&3 echo "$base_toolbox_command: checking if container $toolbox_container exists" >&3
@ -1008,6 +1018,11 @@ enter()
# shellcheck disable=SC2030 # shellcheck disable=SC2030
toolbox_container="$toolbox_container_old" toolbox_container="$toolbox_container_old"
else else
if $pedantic; then
enter_print_container_not_found "$toolbox_container"
exit 1
fi
if ! containers=$(list_container_names); then if ! containers=$(list_container_names); then
enter_print_container_not_found "$toolbox_container" enter_print_container_not_found "$toolbox_container"
exit 1 exit 1
@ -1088,25 +1103,34 @@ enter()
set_environment=$(create_environment_options) set_environment=$(create_environment_options)
echo "$base_toolbox_command: looking for $SHELL in container $toolbox_container" >&3 echo "$base_toolbox_command: looking for $program in container $toolbox_container" >&3
if $prefix_sudo podman exec "$toolbox_container" test -f "$SHELL" 2>&3; then # shellcheck disable=SC2016
shell_to_exec="$SHELL" if ! $prefix_sudo podman exec "$toolbox_container" sh -c 'command -v "$1"' sh "$program" >/dev/null 2>&3; then
else if $fallback_to_bash; then
echo "$base_toolbox_command: $SHELL not found in $toolbox_container; using $shell_to_exec instead" >&3 echo "$base_toolbox_command: $program not found in $toolbox_container; using /bin/bash instead" >&3
program=/bin/bash
else
echo "$base_toolbox_command: command '$program' not found in container $toolbox_container" >&2
exit 127
fi
fi fi
echo "$base_toolbox_command: trying to exec $shell_to_exec in container $toolbox_container" >&3 echo "$base_toolbox_command: running in container $toolbox_container:" >&3
echo "$base_toolbox_command: $program" >&3
for i in "$@"; do
echo "$base_toolbox_command: $i" >&3
done
# shellcheck disable=SC2016 # shellcheck disable=SC2016
# for the command passed to capsh # for the command passed to capsh
# shellcheck disable=SC2086 # shellcheck disable=SC2086
$prefix_sudo podman exec \ $prefix_sudo podman exec \
$set_environment \
--interactive \ --interactive \
--tty \ --tty \
$set_environment \
"$toolbox_container" \ "$toolbox_container" \
capsh --caps="" -- -c 'cd "$1"; shift; exec "$@"' /bin/sh "$PWD" "$shell_to_exec" -l 2>&3 capsh --caps="" -- -c 'cd "$1"; shift; exec "$@"' /bin/sh "$PWD" "$program" "$@" 2>&3
) )
@ -1524,6 +1548,10 @@ usage()
echo " or: toolbox [-y | --assumeyes]" echo " or: toolbox [-y | --assumeyes]"
echo " rmi [-a | --all]" echo " rmi [-a | --all]"
echo " [-f | --force] [<image> ...]" echo " [-f | --force] [<image> ...]"
echo " or: toolbox [-v | --verbose]"
echo " [-y | --assumeyes]"
echo " run [-c | --container <name>]"
echo " [-r | --release <release>] <command>"
echo " or: toolbox --help" echo " or: toolbox --help"
} }
@ -1798,6 +1826,37 @@ case $op in
fi fi
exit exit
;; ;;
run )
if is_integer "$podman_pid"; then
# shellcheck disable=SC2119
forward_to_host
else
while has_prefix "$1" -; do
case $1 in
-c | --container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
-r | --release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo "$1" | sed "s/^F\|^f//" 2>&3)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option "$1"
esac
shift
done
if ! update_container_and_image_names; then
exit 1
fi
run false true "$@"
fi
exit
;;
* ) * )
echo "$base_toolbox_command: unrecognized command '$op'" >&2 echo "$base_toolbox_command: unrecognized command '$op'" >&2
echo "Try '$base_toolbox_command --help' for more information." >&2 echo "Try '$base_toolbox_command --help' for more information." >&2