Skip to content

Commit c1feb56

Browse files
committed
recovery shell quality of life improvements
The recovery shell is quite powerful, but discoverability can be limited. In an attempt to start fixing that, the following has been done: * Add a `help` alias and documentation page listing a few key things that can be done in the recovery shell. * Enable tab completions for the following: set_ro_pool, set_rw_pool, mount_zfs, zfs-chroot/zfs_chroot * Only source aliases/tab completions in interactive shells so that we don't impact the normal ZBM shell environment. Closes #197
1 parent 5876ca9 commit c1feb56

File tree

9 files changed

+276
-5
lines changed

9 files changed

+276
-5
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
NAME
2+
3+
zfsbootmenu - Recovery Shell
4+
5+
Common Commands
6+
7+
zfsbootmenu
8+
Launch the interactive boot environment menu.
9+
10+
zfs-chroot zfs filesystem
11+
Enter a chroot of the specified boot environment. The boot environment is mounted read/write if the zpool is imported read/write.
12+
13+
set_rw_pool pool
14+
Export, then re-import the pool read/write.
15+
16+
set_ro_pool pool
17+
Export, then re-import the pool read-only.
18+
19+
mount_zfs zfs filesystem
20+
Mount the filesystem at a unique location and print the mount point.
21+
22+
help
23+
View the online help system.
24+
25+
logs
26+
View warning/error/debug logs.
27+
28+
AUTHOR
29+
30+
ZFSBootMenu Team <https://github.com/zbm-dev/zfsbootmenu>
31+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
NAME
2+
3+
zfsbootmenu - Recovery Shell
4+
5+
Common Commands
6+
7+
zfsbootmenu
8+
Launch the interactive boot environment menu.
9+
10+
zfs-chroot zfs filesystem
11+
Enter a chroot of the specified boot environment.
12+
The boot environment is mounted read/write if the
13+
zpool is imported read/write.
14+
15+
set_rw_pool pool
16+
Export, then re-import the pool read/write.
17+
18+
set_ro_pool pool
19+
Export, then re-import the pool read-only.
20+
21+
mount_zfs zfs filesystem
22+
Mount the filesystem at a unique location and print
23+
the mount point.
24+
25+
help
26+
View the online help system.
27+
28+
logs
29+
View warning/error/debug logs.
30+
31+
AUTHOR
32+
33+
ZFSBootMenu Team
34+
<https://github.com/zbm-dev/zfsbootmenu>
35+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
NAME
2+
3+
zfsbootmenu - Recovery Shell
4+
5+
Common Commands
6+
7+
zfsbootmenu
8+
Launch the interactive boot environment menu.
9+
10+
zfs-chroot zfs filesystem
11+
Enter a chroot of the specified boot environment. The boot environment is mounted read/write
12+
if the zpool is imported read/write.
13+
14+
set_rw_pool pool
15+
Export, then re-import the pool read/write.
16+
17+
set_ro_pool pool
18+
Export, then re-import the pool read-only.
19+
20+
mount_zfs zfs filesystem
21+
Mount the filesystem at a unique location and print the mount point.
22+
23+
help
24+
View the online help system.
25+
26+
logs
27+
View warning/error/debug logs.
28+
29+
AUTHOR
30+
31+
ZFSBootMenu Team <https://github.com/zbm-dev/zfsbootmenu>
32+

90zfsbootmenu/module-setup.sh

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ install() {
146146
_ret=0
147147
# shellcheck disable=SC2154
148148
inst_simple "${moddir}/zfsbootmenu-lib.sh" "/lib/zfsbootmenu-lib.sh" || _ret=$?
149+
inst_simple "${moddir}/zfsbootmenu-completions.sh" "/lib/zfsbootmenu-completions.sh" || _ret=$?
149150
inst_simple "${moddir}/zfsbootmenu-init.sh" "/libexec/zfsbootmenu-init" || _ret=$?
150151
inst_simple "${moddir}/zfsbootmenu-preview.sh" "/libexec/zfsbootmenu-preview" || _ret=$?
151152
inst_simple "${moddir}/zfsbootmenu-input.sh" "/libexec/zfsbootmenu-input" || _ret=$?
@@ -317,12 +318,29 @@ EOF
317318
cat << EOF >> "${initdir}/etc/profile"
318319
[ -f /lib/zfsbootmenu-lib.sh ] && source /lib/zfsbootmenu-lib.sh
319320
[ -f /etc/zfsbootmenu.conf ] && source /etc/zfsbootmenu.conf
321+
320322
export PATH=/usr/sbin:/usr/bin:/sbin:/bin
321323
export TERM=vt220
324+
325+
zdebug "sourced /etc/profile"
326+
327+
EOF
328+
329+
# Setup a default environment for all login shells
330+
cat << EOF >> "${initdir}/.bashrc"
331+
[ -f /etc/profile ] && source /etc/profile
332+
[ -f /lib/zfsbootmenu-completions.sh ] && source /lib/zfsbootmenu-completions.sh
322333
export PS1="\033[0;33mzfsbootmenu\033[0m \w > "
334+
323335
alias clear="tput clear"
324336
alias reset="tput reset"
325337
alias zbm="zfsbootmenu"
326-
alias logs="zlogtail -f"
338+
alias logs="ztrace"
339+
alias trace="ztrace"
340+
alias debug="ztrace"
341+
alias help="/libexec/zfsbootmenu-help -L recovery-shell"
342+
343+
zdebug "sourced /.bashrc"
344+
327345
EOF
328346
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/bin/bash
2+
# shellcheck disable=SC2207
3+
4+
# disabling this allows completions with the @ character
5+
shopt -u hostcomplete
6+
7+
_zfs-chroot() {
8+
local ZFS
9+
COMPREPLY=()
10+
11+
[ "${#COMP_WORDS[@]}" != "2" ] && return
12+
13+
for SNAP in $( zfs list -H -o name -t snapshot ) ; do
14+
ZFS+=("${SNAP}")
15+
done
16+
17+
for FS in $( zfs list -H -o name ) ; do
18+
ZFS+=("${FS}")
19+
done
20+
21+
COMPREPLY=( $( compgen -W "${ZFS[*]}" -- "${COMP_WORDS[1]}" ) )
22+
}
23+
complete -F _zfs-chroot zfs-chroot
24+
complete -F _zfs-chroot zfs_chroot
25+
26+
_set_rw_pool() {
27+
local ZPOOL
28+
COMPREPLY=()
29+
30+
[ "${#COMP_WORDS[@]}" != "2" ] && return
31+
32+
for POOL in $( zpool list -H -o name ) ; do
33+
if ! is_writable "${POOL}" ; then
34+
ZPOOL+=("${POOL}")
35+
fi
36+
done
37+
COMPREPLY=( $( compgen -W "${ZPOOL[*]}" -- "${COMP_WORDS[1]}" ) )
38+
}
39+
complete -F _set_rw_pool set_rw_pool
40+
41+
_set_ro_pool() {
42+
local ZPOOL
43+
COMPREPLY=()
44+
45+
[ "${#COMP_WORDS[@]}" != "2" ] && return
46+
47+
for POOL in $( zpool list -H -o name ) ; do
48+
if is_writable "${POOL}" ; then
49+
ZPOOL+=("${POOL}")
50+
fi
51+
done
52+
COMPREPLY=( $( compgen -W "${ZPOOL[*]}" -- "${COMP_WORDS[1]}" ) )
53+
}
54+
complete -F _set_ro_pool set_ro_pool
55+
56+
_mount_zfs() {
57+
local ZFS
58+
COMPREPLY=()
59+
60+
[ "${#COMP_WORDS[@]}" != "2" ] && return
61+
62+
for SNAP in $( zfs list -H -o name -t snapshot ) ; do
63+
ZFS+=("${SNAP}")
64+
done
65+
66+
for FS in $( zfs list -H -o name ) ; do
67+
ZFS+=("${FS}")
68+
done
69+
70+
COMPREPLY=( $( compgen -W "${ZFS[*]}" -- "${COMP_WORDS[1]}" ) )
71+
}
72+
complete -F _mount_zfs mount_zfs

90zfsbootmenu/zfsbootmenu-help.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ help_pager() {
2828
SORTED+=("${FINAL}")
2929

3030
printf '%s\n' "${SORTED[@]}" | ${FUZZYSEL} \
31-
--prompt 'Topic >' \
31+
--prompt 'Topic > ' \
3232
--with-nth=2.. \
3333
--bind pgup:preview-up,pgdn:preview-down \
3434
--preview="$0 -s {1}" \
3535
--preview-window="right:${PREVIEW_SIZE}:wrap" \
3636
--header="$( colorize green "[ESC]" ) $( colorize lightblue "back" )" \
3737
--tac \
38+
--inline-info \
3839
--ansi
3940
}
4041

90zfsbootmenu/zfsbootmenu-lib.sh

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,6 +1710,33 @@ set_rw_pool() {
17101710
return 1
17111711
}
17121712

1713+
# arg1: pool name
1714+
# prints: nothing
1715+
# returns: 0 on success, 1 on failure
1716+
1717+
set_ro_pool() {
1718+
local pool ret
1719+
1720+
pool="${1}"
1721+
if [ -z "${pool}" ]; then
1722+
zerror "pool is undefined"
1723+
return 1
1724+
fi
1725+
zdebug "pool set to ${pool}"
1726+
1727+
if export_pool "${pool}" ; then
1728+
read_write='' import_pool "${pool}"
1729+
ret=$?
1730+
1731+
zdebug "import_pool: ${ret}"
1732+
1733+
return ${ret}
1734+
fi
1735+
1736+
return 1
1737+
}
1738+
1739+
17131740
# arg1: ZFS filesystem
17141741
# prints: name of encryption root, if present
17151742
# returns: 0 if system has an encryption root, 1 otherwise
@@ -2082,7 +2109,7 @@ zfs_chroot() {
20822109
# returns: nothing
20832110

20842111
emergency_shell() {
2085-
local message
2112+
local message skip mp fs
20862113
message=${1:-unknown reason}
20872114

20882115
tput clear
@@ -2091,7 +2118,17 @@ emergency_shell() {
20912118

20922119
echo -n "Launching emergency shell: "
20932120
echo -e "${message}\n"
2094-
/bin/bash -l
2121+
2122+
# -i (interactive) mode will source /.bashrc
2123+
/bin/bash -i
2124+
2125+
# shellcheck disable=SC2034
2126+
while read -r skip mp fs skip ; do
2127+
if [ "${fs}" == "zfs" ]; then
2128+
umount "${mp}"
2129+
zdebug "unmounting: ${mp}"
2130+
fi
2131+
done < /proc/self/mounts
20952132
}
20962133

20972134
# prints: nothing

90zfsbootmenu/zfsbootmenu.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ while true; do
299299
# This will make all keys in the pool unavailable, but populate_be_list
300300
# should reload the missing keys in the next iteration, so why unlock here?
301301
if is_writable "${pool}"; then
302-
export_pool "${pool}" && read_write='' import_pool "${pool}"
302+
set_ro_pool "${pool}"
303303
else
304304
set_rw_pool "${pool}"
305305
fi

pod/online/recovery-shell.pod

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
=pod
2+
3+
=head1 NAME
4+
5+
B<zfsbootmenu> - Recovery Shell
6+
7+
=head1 Common Commands
8+
9+
=over 2
10+
11+
=item I<zfsbootmenu>
12+
13+
Launch the interactive boot environment menu.
14+
15+
=item I<zfs-chroot> B<zfs filesystem>
16+
17+
Enter a chroot of the specified boot environment. The boot environment is mounted I<read/write> if the zpool is imported I<read/write>.
18+
19+
=item I<set_rw_pool> B<pool>
20+
21+
Export, then re-import the pool I<read/write>.
22+
23+
=item I<set_ro_pool> B<pool>
24+
25+
Export, then re-import the pool I<read-only>.
26+
27+
=item I<mount_zfs> B<zfs filesystem>
28+
29+
Mount the filesystem at a unique location and print the mount point.
30+
31+
=item I<help>
32+
33+
View the online help system.
34+
35+
=item I<logs>
36+
37+
View warning/error/debug logs.
38+
39+
=back
40+
41+
=head2 AUTHOR
42+
43+
ZFSBootMenu Team L<https://github.com/zbm-dev/zfsbootmenu>
44+
45+
=cut

0 commit comments

Comments
 (0)