initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
backups/
|
||||||
|
chroot_daemon_logs/
|
||||||
50
chroot_manager.1
Normal file
50
chroot_manager.1
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
.\" Manpage for chroot_manager
|
||||||
|
.TH CHROOT_MANAGER 1 "February 2025" "chroot_manager 1.0" "User Commands"
|
||||||
|
.SH NAME
|
||||||
|
chroot_manager \- chroot management tool with daemon logging support
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B chroot_manager
|
||||||
|
[--verbose] [--daemon] <command>
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The
|
||||||
|
.B chroot_manager
|
||||||
|
script provides commands to create, connect to, disconnect from, and manage a chroot jail.
|
||||||
|
.PP
|
||||||
|
It also supports a daemon mode (using --daemon) where the chroot session is run under
|
||||||
|
strace to log all system calls from the chroot environment and its child processes.
|
||||||
|
.PP
|
||||||
|
Available commands:
|
||||||
|
.TP
|
||||||
|
.B create
|
||||||
|
Creates a chroot jail using debootstrap.
|
||||||
|
.TP
|
||||||
|
.B connect
|
||||||
|
Mounts required filesystems, sets up X access, and enters the chroot.
|
||||||
|
With --daemon, the session is traced via strace.
|
||||||
|
.TP
|
||||||
|
.B disconnect
|
||||||
|
Unmounts the filesystems from the chroot.
|
||||||
|
.TP
|
||||||
|
.B status
|
||||||
|
Shows the mount status for the chroot jail.
|
||||||
|
.TP
|
||||||
|
.B install
|
||||||
|
Installs chroot_manager to /usr/local/bin along with its man page and shell completions.
|
||||||
|
.TP
|
||||||
|
.B uninstall
|
||||||
|
Removes the installed chroot_manager, its man page, and shell completions.
|
||||||
|
.TP
|
||||||
|
.B help
|
||||||
|
Displays this help message.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B --verbose
|
||||||
|
Enables verbose output.
|
||||||
|
.TP
|
||||||
|
.B --daemon
|
||||||
|
Enables daemon mode for the connect command.
|
||||||
|
.SH AUTHOR
|
||||||
|
Written by Your Name.
|
||||||
|
.SH COPYRIGHT
|
||||||
|
This is free software; see the source for copying conditions. There is NO warranty.
|
||||||
|
|
||||||
21
chroot_manager.bash_completion
Normal file
21
chroot_manager.bash_completion
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Bash completion for chroot_manager
|
||||||
|
|
||||||
|
_chroot_manager_completion() {
|
||||||
|
local cur prev opts cmds
|
||||||
|
COMPREPLY=()
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
|
||||||
|
cmds="create connect disconnect status install uninstall help"
|
||||||
|
opts="--verbose --daemon --help -h"
|
||||||
|
|
||||||
|
if [[ ${COMP_CWORD} == 1 ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "${cmds} ${opts}" -- ${cur}) )
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _chroot_manager_completion chroot_manager
|
||||||
|
|
||||||
494
chroot_manager.sh
Executable file
494
chroot_manager.sh
Executable file
@@ -0,0 +1,494 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# chroot_manager.sh
|
||||||
|
#
|
||||||
|
# A fully featured chroot management tool with:
|
||||||
|
# - A command-line interface (create, connect, disconnect, status, help, install, uninstall)
|
||||||
|
# - Improved error handling and logging
|
||||||
|
# - A verbose/debug mode (--verbose)
|
||||||
|
# - A daemon mode (--daemon) which, when used with connect, will run
|
||||||
|
# the chroot session under strace to log all activity (system calls) in separate files.
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# - Some commands (create, connect, disconnect, install, uninstall) must be run as root.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# sudo ./chroot_manager.sh [--verbose] [--daemon] <command>
|
||||||
|
#
|
||||||
|
# Commands:
|
||||||
|
# create Create the chroot jail using debootstrap.
|
||||||
|
# connect Mount necessary filesystems, set up X access, and enter the chroot.
|
||||||
|
# With --daemon, the session is run under strace to log all activity.
|
||||||
|
# disconnect Unmount the filesystems from the chroot (if needed).
|
||||||
|
# status Display the current mount status for the chroot jail.
|
||||||
|
# help Display a detailed help message.
|
||||||
|
# install Install chroot_manager to /usr/local/bin (and install man page and shell completions).
|
||||||
|
# uninstall Uninstall chroot_manager and remove its man page and shell completions.
|
||||||
|
#
|
||||||
|
# Note:
|
||||||
|
# By default, the script assumes the chroot jail is located at /var/chroot.
|
||||||
|
# When using --daemon, the log files will be stored in a directory created in the
|
||||||
|
# current working directory (default: "chroot_daemon_logs"). After the chroot session ends,
|
||||||
|
# the script will attempt to rename each log file based on the traced program’s name (if available)
|
||||||
|
# and ignore logs for trivial commands. Finally, the script will adjust ownership and permissions
|
||||||
|
# on that directory and its contents so they are accessible to the invoking user.
|
||||||
|
#
|
||||||
|
|
||||||
|
# --- Global Variables and Defaults ---
|
||||||
|
CHROOT_DIR="/var/chroot"
|
||||||
|
DEBIAN_MIRROR="http://deb.debian.org/debian"
|
||||||
|
LOGFILE="/var/log/chroot_manager.log"
|
||||||
|
VERBOSE=0
|
||||||
|
DAEMON=0
|
||||||
|
# Default directory to store daemon logs
|
||||||
|
DAEMON_LOG_DIR="$(pwd)/chroot_daemon_logs"
|
||||||
|
|
||||||
|
# List of trivial commands to ignore in daemon logs (basename only)
|
||||||
|
IGNORE_LIST=(bash sh ls cat echo grep mount umount)
|
||||||
|
|
||||||
|
# --- Logging Functions ---
|
||||||
|
function log_info() {
|
||||||
|
echo "[INFO] $(date +'%F %T') $*" | tee -a "$LOGFILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_debug() {
|
||||||
|
if [ "$VERBOSE" -eq 1 ]; then
|
||||||
|
echo "[DEBUG] $(date +'%F %T') $*" | tee -a "$LOGFILE"
|
||||||
|
else
|
||||||
|
echo "[DEBUG] $(date +'%F %T') $*" >> "$LOGFILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error() {
|
||||||
|
echo "[ERROR] $(date +'%F %T') $*" | tee -a "$LOGFILE" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Extended Help Message ---
|
||||||
|
function help_message() {
|
||||||
|
cat <<EOF
|
||||||
|
chroot_manager.sh - A chroot management tool
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
sudo $0 [--verbose] [--daemon] <command>
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
create
|
||||||
|
Create the chroot jail using debootstrap.
|
||||||
|
Sets up a minimal Debian environment in \$CHROOT_DIR.
|
||||||
|
|
||||||
|
connect
|
||||||
|
Mount necessary filesystems (dev, proc, sys, tmp) into the chroot,
|
||||||
|
set up X access, and then enter the chroot environment.
|
||||||
|
When the chroot session ends, the bind mounts are automatically cleaned up.
|
||||||
|
With the --daemon flag, the session is launched under strace so that every system call
|
||||||
|
from the chroot process and its children is logged. The logs are stored in a directory:
|
||||||
|
\$DAEMON_LOG_DIR
|
||||||
|
Each log file is post-processed to try to include the traced program's name (if found)
|
||||||
|
and trivial commands are ignored. Finally, the log directory and its files will have their
|
||||||
|
ownership and permissions changed so the invoking user (from \$SUDO_USER) can read and write them.
|
||||||
|
|
||||||
|
disconnect
|
||||||
|
Unmount the filesystems from the chroot.
|
||||||
|
Checks if bind mounts exist for \$CHROOT_DIR and, if so, unmounts them.
|
||||||
|
|
||||||
|
status
|
||||||
|
Displays the current mount status for the chroot jail (\$CHROOT_DIR).
|
||||||
|
|
||||||
|
install
|
||||||
|
Installs chroot_manager to /usr/local/bin, and copies the man page and bash completion file
|
||||||
|
(if found in the current directory) to the appropriate locations.
|
||||||
|
|
||||||
|
uninstall
|
||||||
|
Uninstalls chroot_manager from /usr/local/bin and removes the installed man page and bash completion file.
|
||||||
|
|
||||||
|
help
|
||||||
|
Display this detailed help message.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--verbose
|
||||||
|
Enable verbose/debug mode (more detailed logging to console and log file).
|
||||||
|
|
||||||
|
--daemon
|
||||||
|
When used with the 'connect' command, run the chroot session under strace in daemon mode,
|
||||||
|
logging all system call activity in separate log files.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Commands that modify the chroot environment (create, connect, disconnect, install, uninstall)
|
||||||
|
must be run as root.
|
||||||
|
- By default, the chroot jail is located at: \$CHROOT_DIR.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Usage (Short) ---
|
||||||
|
function usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [--verbose] [--daemon] <command>
|
||||||
|
Try '$0 help' for more information.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Dependency Check ---
|
||||||
|
REQUIRED_CMDS=(debootstrap chroot mount xhost xauth sudo strace)
|
||||||
|
function check_dependencies() {
|
||||||
|
local missing=0
|
||||||
|
for cmd in "${REQUIRED_CMDS[@]}"; do
|
||||||
|
if ! command -v "$cmd" &>/dev/null; then
|
||||||
|
log_error "Required command '$cmd' is not installed."
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ $missing -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Check for Chroot Jail Existence ---
|
||||||
|
function check_jail() {
|
||||||
|
if [ ! -d "$CHROOT_DIR" ]; then
|
||||||
|
log_error "Chroot jail '$CHROOT_DIR' does not exist."
|
||||||
|
echo "Please create the chroot environment first using the 'create' command."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Mount / Unmount Filesystems ---
|
||||||
|
function mount_filesystems() {
|
||||||
|
local dirs=(dev proc sys tmp)
|
||||||
|
for d in "${dirs[@]}"; do
|
||||||
|
log_info "Mounting /$d to ${CHROOT_DIR}/$d..."
|
||||||
|
if ! mountpoint -q "${CHROOT_DIR}/$d"; then
|
||||||
|
if ! sudo mount --bind "/$d" "${CHROOT_DIR}/$d"; then
|
||||||
|
log_error "Error mounting /$d"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_debug "${CHROOT_DIR}/$d is already mounted."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmount_filesystems() {
|
||||||
|
local dirs=(dev proc sys tmp)
|
||||||
|
local any_mounted=0
|
||||||
|
for d in "${dirs[@]}"; do
|
||||||
|
if mountpoint -q "${CHROOT_DIR}/$d"; then
|
||||||
|
any_mounted=1
|
||||||
|
log_info "Unmounting ${CHROOT_DIR}/$d..."
|
||||||
|
if ! sudo umount "${CHROOT_DIR}/$d"; then
|
||||||
|
log_error "Error unmounting ${CHROOT_DIR}/$d"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_debug "${CHROOT_DIR}/$d is not mounted."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return $any_mounted
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Post-Process Daemon Logs ---
|
||||||
|
function post_process_daemon_logs() {
|
||||||
|
log_info "Post-processing daemon logs in directory: $DAEMON_LOG_DIR"
|
||||||
|
# Iterate over log files matching the pattern (they are created with suffix .<pid>)
|
||||||
|
for logfile in "$DAEMON_LOG_DIR"/chroot_daemon.log.*; do
|
||||||
|
[ -e "$logfile" ] || continue
|
||||||
|
# Extract the PID from the filename: assume filename ends with .<pid>
|
||||||
|
pid="${logfile##*.}"
|
||||||
|
# Try to extract the first execve call to determine the program name.
|
||||||
|
prog_full=$(grep -m 1 'execve(' "$logfile" | sed -E 's/.*execve\("([^"]+)".*/\1/')
|
||||||
|
if [ -n "$prog_full" ]; then
|
||||||
|
prog_name=$(basename "$prog_full")
|
||||||
|
else
|
||||||
|
prog_name="pid${pid}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the program is in the ignore list (compare only the basename)
|
||||||
|
ignore=0
|
||||||
|
for trivial in "${IGNORE_LIST[@]}"; do
|
||||||
|
if [ "$prog_name" == "$trivial" ]; then
|
||||||
|
ignore=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$ignore" -eq 1 ]; then
|
||||||
|
log_debug "Ignoring trivial log for program '$prog_name' (file: $logfile). Removing."
|
||||||
|
rm -f "$logfile"
|
||||||
|
else
|
||||||
|
newname="$DAEMON_LOG_DIR/${prog_name}_${pid}.log"
|
||||||
|
log_info "Renaming log file '$logfile' to '$newname'"
|
||||||
|
mv "$logfile" "$newname"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Adjust ownership and permissions of the daemon log directory and its contents.
|
||||||
|
if [ -n "$SUDO_USER" ]; then
|
||||||
|
log_info "Changing ownership of $DAEMON_LOG_DIR to user $SUDO_USER"
|
||||||
|
sudo chown -R "$SUDO_USER":"$SUDO_USER" "$DAEMON_LOG_DIR"
|
||||||
|
fi
|
||||||
|
log_info "Setting permissions on $DAEMON_LOG_DIR and its files."
|
||||||
|
# Directories: rwxr-xr-x; Files: rw-r--r--
|
||||||
|
find "$DAEMON_LOG_DIR" -type d -exec chmod 0755 {} \;
|
||||||
|
find "$DAEMON_LOG_DIR" -type f -exec chmod 0644 {} \;
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Cleanup Routine (for connect) ---
|
||||||
|
function cleanup() {
|
||||||
|
log_info "Cleaning up: Unmounting filesystems..."
|
||||||
|
unmount_filesystems
|
||||||
|
log_info "Cleanup complete."
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Command: create ---
|
||||||
|
function create() {
|
||||||
|
# Require root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Error: The 'create' command must be run as root (use sudo)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_dependencies
|
||||||
|
if [ -d "$CHROOT_DIR" ]; then
|
||||||
|
log_error "Chroot jail already exists at $CHROOT_DIR."
|
||||||
|
echo "Use 'connect' to enter it, or 'disconnect' if mounts remain."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Creating chroot jail at $CHROOT_DIR using debootstrap..."
|
||||||
|
if ! sudo mkdir -p "$CHROOT_DIR"; then
|
||||||
|
log_error "Failed to create directory $CHROOT_DIR."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if sudo debootstrap stable "$CHROOT_DIR" "$DEBIAN_MIRROR"; then
|
||||||
|
log_info "Chroot jail successfully created."
|
||||||
|
else
|
||||||
|
log_error "debootstrap failed. Check your network and settings."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Command: connect ---
|
||||||
|
function connect() {
|
||||||
|
# Require root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Error: The 'connect' command must be run as root (use sudo)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_dependencies
|
||||||
|
check_jail
|
||||||
|
|
||||||
|
# Set trap for cleanup when connect ends.
|
||||||
|
trap cleanup EXIT SIGINT SIGTERM SIGHUP
|
||||||
|
|
||||||
|
# Mount the required filesystems
|
||||||
|
mount_filesystems
|
||||||
|
|
||||||
|
# Allow all connections to the X server
|
||||||
|
log_info "Running 'xhost +' to allow X connections..."
|
||||||
|
if ! xhost +; then
|
||||||
|
log_error "Error running 'xhost +'."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the current X authentication keys
|
||||||
|
log_info "Retrieving X authentication keys with 'xauth list'..."
|
||||||
|
local xauth_keys
|
||||||
|
xauth_keys=$(xauth list)
|
||||||
|
if [ -z "$xauth_keys" ]; then
|
||||||
|
log_error "Warning: 'xauth list' returned no output."
|
||||||
|
else
|
||||||
|
if command -v xclip &>/dev/null; then
|
||||||
|
echo "$xauth_keys" | xclip -selection clipboard
|
||||||
|
log_info "X authentication keys have been copied to your clipboard."
|
||||||
|
else
|
||||||
|
log_info "xclip not found. Here are your X authentication keys:"
|
||||||
|
echo "$xauth_keys"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "------------------------------"
|
||||||
|
echo "Now entering the chroot environment."
|
||||||
|
echo "Inside the chroot, add the X authentication key by running:"
|
||||||
|
echo " xauth add <paste-from-clipboard>"
|
||||||
|
echo "For example, if your clipboard contains:"
|
||||||
|
echo " $(echo "$xauth_keys" | head -n 1)"
|
||||||
|
echo "then run:"
|
||||||
|
echo " xauth add $(echo "$xauth_keys" | head -n 1)"
|
||||||
|
echo "------------------------------"
|
||||||
|
echo "Press Enter to continue..."
|
||||||
|
read -r
|
||||||
|
|
||||||
|
log_info "Entering chroot at $CHROOT_DIR..."
|
||||||
|
if [ "$DAEMON" -eq 1 ]; then
|
||||||
|
# Create the daemon log directory if it doesn't exist.
|
||||||
|
if [ ! -d "$DAEMON_LOG_DIR" ]; then
|
||||||
|
mkdir -p "$DAEMON_LOG_DIR" || {
|
||||||
|
log_error "Failed to create daemon log directory: $DAEMON_LOG_DIR"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
log_info "Daemon mode enabled. Monitoring chroot session with strace."
|
||||||
|
# Run chroot under strace so that all system calls (and those of forked children)
|
||||||
|
# are logged to files with prefix "$DAEMON_LOG_DIR/chroot_daemon.log"
|
||||||
|
strace -ff -tt -o "$DAEMON_LOG_DIR/chroot_daemon.log" sudo chroot "$CHROOT_DIR"
|
||||||
|
# Post-process the generated logs
|
||||||
|
post_process_daemon_logs
|
||||||
|
else
|
||||||
|
sudo chroot "$CHROOT_DIR"
|
||||||
|
fi
|
||||||
|
log_info "Chroot session ended."
|
||||||
|
# When the chroot session ends, cleanup is automatically triggered by trap.
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Command: disconnect ---
|
||||||
|
function disconnect() {
|
||||||
|
# Require root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Error: The 'disconnect' command must be run as root (use sudo)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_jail
|
||||||
|
|
||||||
|
# Check if any bind mounts exist.
|
||||||
|
if ! mount | grep -q "$CHROOT_DIR"; then
|
||||||
|
log_info "Chroot environment appears to be clean; no mounts found at $CHROOT_DIR."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Running disconnect: unmounting chroot filesystems..."
|
||||||
|
unmount_filesystems
|
||||||
|
|
||||||
|
# Revoke X server permissions.
|
||||||
|
if xhost -; then
|
||||||
|
log_info "X server access has been revoked."
|
||||||
|
else
|
||||||
|
log_error "Warning: failed to revoke X server permissions with 'xhost -'."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Command: status ---
|
||||||
|
function status() {
|
||||||
|
echo "Mount status for chroot jail ($CHROOT_DIR):"
|
||||||
|
mount | grep "$CHROOT_DIR" || echo "No mounts found for $CHROOT_DIR."
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Command: install ---
|
||||||
|
function install_program() {
|
||||||
|
# Require root.
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Error: The 'install' command must be run as root (use sudo)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Resolve the full path of the current script.
|
||||||
|
script_path=$(readlink -f "$0")
|
||||||
|
log_info "Installing chroot_manager from $script_path to /usr/local/bin/chroot_manager..."
|
||||||
|
cp "$script_path" /usr/local/bin/chroot_manager || { log_error "Failed to copy script."; exit 1; }
|
||||||
|
chmod 0755 /usr/local/bin/chroot_manager
|
||||||
|
|
||||||
|
# Install the man page if available.
|
||||||
|
if [ -e "chroot_manager.1" ]; then
|
||||||
|
log_info "Installing man page..."
|
||||||
|
mkdir -p /usr/local/share/man/man1
|
||||||
|
cp chroot_manager.1 /usr/local/share/man/man1/chroot_manager.1 || { log_error "Failed to copy man page."; }
|
||||||
|
gzip -f /usr/local/share/man/man1/chroot_manager.1
|
||||||
|
else
|
||||||
|
log_debug "No man page (chroot_manager.1) found in the current directory."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install bash completions if available.
|
||||||
|
if [ -e "chroot_manager.bash_completion" ]; then
|
||||||
|
log_info "Installing bash completion..."
|
||||||
|
cp chroot_manager.bash_completion /etc/bash_completion.d/chroot_manager || { log_error "Failed to install bash completion."; }
|
||||||
|
else
|
||||||
|
log_debug "No bash completion file found in the current directory."
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Installation complete."
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Command: uninstall ---
|
||||||
|
function uninstall_program() {
|
||||||
|
# Require root.
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Error: The 'uninstall' command must be run as root (use sudo)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Uninstalling chroot_manager from /usr/local/bin..."
|
||||||
|
rm -f /usr/local/bin/chroot_manager
|
||||||
|
|
||||||
|
log_info "Removing man page..."
|
||||||
|
rm -f /usr/local/share/man/man1/chroot_manager.1.gz
|
||||||
|
|
||||||
|
log_info "Removing bash completion..."
|
||||||
|
rm -f /etc/bash_completion.d/chroot_manager
|
||||||
|
|
||||||
|
log_info "Uninstallation complete."
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Main CLI Processing ---
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process options.
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help)
|
||||||
|
help_message
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--verbose)
|
||||||
|
VERBOSE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--daemon)
|
||||||
|
DAEMON=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
create|connect|disconnect|status|install|uninstall|help)
|
||||||
|
COMMAND="$1"
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option or command: $1"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Dispatch command.
|
||||||
|
case "$COMMAND" in
|
||||||
|
create)
|
||||||
|
create
|
||||||
|
;;
|
||||||
|
connect)
|
||||||
|
connect
|
||||||
|
;;
|
||||||
|
disconnect)
|
||||||
|
disconnect
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
install)
|
||||||
|
install_program
|
||||||
|
;;
|
||||||
|
uninstall)
|
||||||
|
uninstall_program
|
||||||
|
;;
|
||||||
|
help)
|
||||||
|
help_message
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid command."
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
Reference in New Issue
Block a user