Skip to content

Instantly share code, notes, and snippets.

@superyngo
Last active December 30, 2025 01:56
Show Gist options
  • Select an option

  • Save superyngo/7ff78b1ccc213ff6a6cb3b1b2dbd77d0 to your computer and use it in GitHub Desktop.

Select an option

Save superyngo/7ff78b1ccc213ff6a6cb3b1b2dbd77d0 to your computer and use it in GitHub Desktop.
Manage logrotate configurations
#!/usr/bin/env bash
# wrtman - Manage logrotate configurations
# Usage:
# ./wrtman.sh install [rotate_name]
# ./wrtman.sh uninstall [rotate_name]
# ./wrtman.sh info [rotate_name]
# ./wrtman.sh list
# ./wrtman.sh test [rotate_name]
# v0.2.1 fix config permission, add permission check for testing
set -euo pipefail
# Configuration
readonly ROTATE_DIR="/etc/logrotate.d"
readonly SELF_UID="$(id -u)"
readonly SELF_GID="$(id -g)"
readonly SELF_USER="$(id -un)"
readonly SELF_GROUP="$(id -gn)"
# Colors for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Generate logrotate configuration
generate_config() {
local -n logs_ref=$1
cat <<EOF
# Generated by wrtman
# Log files: ${logs_ref[*]}
${logs_ref[*]} {
# Rotation schedule
daily
rotate 14
# Compression
compress
delaycompress
# Error handling
missingok
notifempty
# File permissions
create 0644 $SELF_USER $SELF_GROUP
# Date format in rotated files (optional)
dateext
dateformat -%Y%m%d
# Post-rotation script (optional)
# postrotate
# /usr/bin/systemctl reload your-service > /dev/null 2>&1 || true
# endscript
}
EOF
}
# Logging functions
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
log_success() { echo -e "${GREEN}[OK]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_info() { echo "[INFO] $*"; }
# Check if running with sudo/root
require_sudo() {
if [[ $EUID -eq 0 ]]; then
return 0
fi
if ! command -v sudo >/dev/null 2>&1; then
log_error "This operation requires sudo, but sudo is not installed"
exit 1
fi
if ! sudo -n true 2>/dev/null; then
log_error "This operation requires sudo privileges"
log_info "Run: sudo $0 $*"
exit 1
fi
}
# Validate rotation name
validate_rotate_name() {
local name="$1"
if [[ -z "$name" ]]; then
log_error "Rotation name cannot be empty"
return 1
fi
if [[ ! "$name" =~ ^[a-zA-Z0-9._-]+$ ]]; then
log_error "Invalid rotation name: '$name'"
log_info "Name must contain only alphanumeric characters, dots, underscores, and hyphens"
return 1
fi
if [[ "${#name}" -gt 255 ]]; then
log_error "Rotation name too long (max 255 characters)"
return 1
fi
return 0
}
# Validate log path
validate_log_path() {
local path="$1"
if [[ -z "$path" ]]; then
log_error "Log path cannot be empty"
return 1
fi
if [[ "$path" != /* ]]; then
log_error "Log path must be absolute: '$path'"
return 1
fi
# Check for suspicious paths
if [[ "$path" =~ ^/etc/|^/boot/|^/sys/|^/proc/|^/dev/ ]]; then
log_error "Cannot rotate system directory logs: '$path'"
return 1
fi
return 0
}
# Create log file if it doesn't exist
ensure_log_file() {
local log="$1"
local dir
dir="$(dirname "$log")"
if [[ ! -f "$log" ]]; then
log_info "Creating log file: $log"
if [[ ! -d "$dir" ]]; then
sudo mkdir -p "$dir" || {
log_error "Failed to create directory: $dir"
return 1
}
fi
sudo touch "$log" || {
log_error "Failed to create log file: $log"
return 1
}
sudo chown "$SELF_UID:$SELF_GID" "$log" || {
log_warn "Could not change ownership of $log"
}
sudo chmod 644 "$log" || {
log_warn "Could not change permissions of $log"
}
fi
return 0
}
check_root_owner() {
local config_path="$1"
if [ "$(stat -c %u "$config_path")" -eq 0 ]; then
log_success "Permission OK: owner is root"
return 0
else
log_error "Permission error: owner is not root"
return 1
fi
}
# Test logrotate configuration
test_config() {
local config_file="$1"
if ! command -v logrotate >/dev/null 2>&1; then
log_warn "logrotate command not found, skipping validation"
return 0
fi
log_info "Testing configuration..."
# Create a temporary copy owned by root for testing
local test_file="/tmp/logrotate-test-$"
sudo cp "$config_file" "$test_file"
sudo chown root:root "$test_file"
sudo chmod 644 "$test_file"
# Capture both stdout and stderr
local test_output
test_output=$(sudo logrotate -d "$test_file" 2>&1)
local test_result=$?
# Clean up test file
sudo rm -f "$test_file"
# Check for actual errors (ignore warnings about debug mode)
if echo "$test_output" | grep -i "error:" | grep -v "file owner is wrong" >/dev/null; then
log_error "Configuration test failed"
echo "$test_output" | grep -i "error:"
return 1
fi
log_success "Configuration is valid"
return 0
}
# Install logrotate configuration
install() {
require_sudo "$@"
local rotate_name="$1"
# Prompt for name if not provided
if [[ -z "$rotate_name" ]]; then
read -rp "Enter rotation config name: " rotate_name
fi
validate_rotate_name "$rotate_name" || exit 1
local config_path="$ROTATE_DIR/$rotate_name"
# Check if already exists
if [[ -f "$config_path" ]]; then
log_warn "Configuration already exists: $config_path"
read -rp "Overwrite? (y/N): " confirm
[[ "$confirm" != [yY] ]] && { log_info "Aborted"; exit 0; }
fi
# Collect log paths
echo "Enter log file paths (one per line, empty line to finish):"
local -a logs=()
while IFS= read -r line; do
[[ -z "$line" ]] && break
if validate_log_path "$line"; then
logs+=("$line")
log_success "Added: $line"
else
log_error "Skipped invalid path: $line"
fi
done
if [[ ${#logs[@]} -eq 0 ]]; then
log_error "No valid log paths provided"
exit 1
fi
# Create log files if needed
for log in "${logs[@]}"; do
ensure_log_file "$log" || exit 1
done
# Generate and install config
local tmp_config
tmp_config="$(mktemp)"
trap 'rm -f "$tmp_config"' EXIT
generate_config logs > "$tmp_config"
log_info "Generated configuration:"
cat "$tmp_config"
echo
# Test configuration
if ! test_config "$tmp_config"; then
log_error "Installation aborted due to configuration errors"
exit 1
fi
# Install
sudo mv "$tmp_config" "$config_path" || {
log_error "Failed to install configuration"
exit 1
}
sudo chmod 644 "$config_path"
sudo chown root:root "$config_path"
log_success "Installed: $config_path"
log_info "Logs will be rotated according to the schedule"
}
# Uninstall logrotate configuration
uninstall() {
require_sudo "$@"
local rotate_name="$1"
if [[ -z "$rotate_name" ]]; then
read -rp "Enter rotation config name to remove: " rotate_name
fi
validate_rotate_name "$rotate_name" || exit 1
local config_path="$ROTATE_DIR/$rotate_name"
if [[ ! -f "$config_path" ]]; then
log_error "Configuration not found: $config_path"
exit 1
fi
# Show what will be removed
log_info "Configuration to remove:"
cat "$config_path"
echo
read -rp "Remove this configuration? (y/N): " confirm
[[ "$confirm" != [yY] ]] && { log_info "Aborted"; exit 0; }
sudo rm -f "$config_path" || {
log_error "Failed to remove configuration"
exit 1
}
log_success "Removed: $config_path"
}
# Show information about a configuration
info() {
local rotate_name="$1"
if [[ -z "$rotate_name" ]]; then
read -rp "Enter rotation config name: " rotate_name
fi
validate_rotate_name "$rotate_name" || exit 1
local config_path="$ROTATE_DIR/$rotate_name"
if [[ ! -f "$config_path" ]]; then
log_error "Configuration not found: $config_path"
exit 1
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Configuration: $rotate_name"
echo "Path: $config_path"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo "=== Configuration Content ==="
cat "$config_path"
echo
echo "=== Log Files Status ==="
# Extract log paths from config (handles multi-line log definitions)
awk '
# Collect all lines until we hit the opening brace
/^[^#]/ && !found_brace {
line = line " " $0
if ($0 ~ /{/) {
found_brace = 1
gsub(/{/, "", line)
# Split the line into words and print each non-comment word
n = split(line, words)
for (i = 1; i <= n; i++) {
if (words[i] !~ /^#/ && words[i] != "") {
print words[i]
}
}
}
}
' "$config_path" | while IFS= read -r log; do
if [[ -n "$log" && "$log" != "{" ]]; then
if [[ -f "$log" ]]; then
local size
size=$(du -h "$log" 2>/dev/null | cut -f1)
log_success "$log (size: $size)"
else
log_warn "$log (missing)"
fi
fi
done
echo
# Calculate rotated files statistics
echo "=== Rotated Files Statistics ==="
local total_rotated=0
local total_size=0
# Get all log paths into an array
local -a log_paths=()
while IFS= read -r log; do
[[ -n "$log" && "$log" != "{" ]] && log_paths+=("$log")
done < <(awk '
/^[^#]/ && !found_brace {
line = line " " $0
if ($0 ~ /{/) {
found_brace = 1
gsub(/{/, "", line)
n = split(line, words)
for (i = 1; i <= n; i++) {
if (words[i] !~ /^#/ && words[i] != "") {
print words[i]
}
}
}
}
' "$config_path")
# Process each log path
for log in "${log_paths[@]}"; do
# Check if main log file exists (use sudo for permission-restricted files)
if ! sudo test -f "$log" 2>/dev/null && [[ ! -f "$log" ]]; then
continue
fi
local rotated_count=0
local rotated_size=0
local log_dir
local log_base
log_dir=$(dirname "$log")
log_base=$(basename "$log")
# Get all rotated files into an array (use sudo for permission-restricted directories)
local -a rotated_files=()
while IFS= read -r -d '' rotated_file; do
rotated_files+=("$rotated_file")
done < <(sudo find "$log_dir" -maxdepth 1 -type f -name "${log_base}*" -print0 2>/dev/null)
# Calculate stats for rotated files
for rotated_file in "${rotated_files[@]}"; do
# Skip the main log file itself
[[ "$rotated_file" == "$log" ]] && continue
# Get file size in bytes using stat (use sudo for permission-restricted files)
if sudo test -f "$rotated_file" 2>/dev/null; then
local file_size
# Try Linux stat first, then BSD stat (use sudo)
file_size=$(sudo stat -c%s "$rotated_file" 2>/dev/null || sudo stat -f%z "$rotated_file" 2>/dev/null || echo 0)
# Only count if we got a valid size
if [[ "$file_size" =~ ^[0-9]+$ ]]; then
((rotated_count++)) || true
((rotated_size += file_size)) || true
fi
fi
done
# Display stats for this log if it has rotated files
if [[ $rotated_count -gt 0 ]]; then
# Convert bytes to MB
local size_mb
size_mb=$(awk "BEGIN {printf \"%.2f\", $rotated_size / 1024 / 1024}")
echo " $log_base: $rotated_count file(s), ${size_mb} MB"
((total_rotated += rotated_count)) || true
((total_size += rotated_size)) || true
fi
done
# Show total or no files message
if [[ $total_rotated -gt 0 ]]; then
local total_mb
total_mb=$(awk "BEGIN {printf \"%.2f\", $total_size / 1024 / 1024}")
echo
echo "Total: $total_rotated rotated file(s), ${total_mb} MB"
else
log_info "No rotated files found"
fi
}
# List all configurations
list() {
if [[ ! -d "$ROTATE_DIR" ]]; then
log_error "Logrotate directory not found: $ROTATE_DIR"
exit 1
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Logrotate Configurations in $ROTATE_DIR"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local count=0
# Use ls with proper error handling
if ls -1 "$ROTATE_DIR" 2>/dev/null | sort | while IFS= read -r file; do
# Skip if it's a directory
[[ -d "$ROTATE_DIR/$file" ]] && continue
echo " • $file"
((count++))
done; then
:
fi
# Count files directly
count=$(find "$ROTATE_DIR" -maxdepth 1 -type f 2>/dev/null | wc -l)
echo
if [[ $count -eq 0 ]]; then
log_info "No configurations found"
else
echo "Total: $count configuration(s)"
fi
}
# Test a specific configuration
test() {
local rotate_name="$1"
if [[ -z "$rotate_name" ]]; then
read -rp "Enter rotation config name to test: " rotate_name
fi
validate_rotate_name "$rotate_name" || exit 1
local config_path="$ROTATE_DIR/$rotate_name"
if [[ ! -f "$config_path" ]]; then
log_error "Configuration not found: $config_path"
exit 1
fi
test_config "$config_path"
check_root_owner "$config_path"
}
# clean rotated log files
clean() {
require_sudo "$@"
local rotate_name="$1"
if [[ -z "$rotate_name" ]]; then
read -rp "Enter rotation config name: " rotate_name
fi
validate_rotate_name "$rotate_name" || exit 1
local config_path="$ROTATE_DIR/$rotate_name"
if [[ ! -f "$config_path" ]]; then
log_error "Configuration not found: $config_path"
exit 1
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "clean Log Files for: $rotate_name"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
# Get all log paths into an array
local -a log_paths=()
while IFS= read -r log; do
[[ -n "$log" && "$log" != "{" ]] && log_paths+=("$log")
done < <(awk '
/^[^#]/ && !found_brace {
line = line " " $0
if ($0 ~ /{/) {
found_brace = 1
gsub(/{/, "", line)
n = split(line, words)
for (i = 1; i <= n; i++) {
if (words[i] !~ /^#/ && words[i] != "") {
print words[i]
}
}
}
}
' "$config_path")
if [[ ${#log_paths[@]} -eq 0 ]]; then
log_error "No log paths found in configuration"
exit 1
fi
# Collect all rotated files
local -a all_files=()
local total_size=0
local total_count=0
for log in "${log_paths[@]}"; do
# Check if main log file exists
if ! sudo test -f "$log" 2>/dev/null && [[ ! -f "$log" ]]; then
continue
fi
local log_dir
local log_base
log_dir=$(dirname "$log")
log_base=$(basename "$log")
# Find all rotated files (excluding main log)
while IFS= read -r -d '' rotated_file; do
# Skip the main log file itself
[[ "$rotated_file" == "$log" ]] && continue
if sudo test -f "$rotated_file" 2>/dev/null; then
all_files+=("$rotated_file")
# Get file size
local file_size
file_size=$(sudo stat -c%s "$rotated_file" 2>/dev/null || sudo stat -f%z "$rotated_file" 2>/dev/null || echo 0)
if [[ "$file_size" =~ ^[0-9]+$ ]]; then
((total_size += file_size)) || true
((total_count++)) || true
fi
fi
done < <(sudo find "$log_dir" -maxdepth 1 -type f -name "${log_base}*" -print0 2>/dev/null)
done
if [[ ${#all_files[@]} -eq 0 ]]; then
log_info "No rotated files found to clean"
exit 0
fi
# Show files to be deleted
echo "Files to be deleted:"
for file in "${all_files[@]}"; do
echo " • $file"
done
echo
# Show statistics
local total_mb
total_mb=$(awk "BEGIN {printf \"%.2f\", $total_size / 1024 / 1024}")
log_warn "Total: $total_count file(s), ${total_mb} MB will be deleted"
echo
# Confirm deletion
read -rp "Delete all rotated log files? (y/N): " confirm
[[ "$confirm" != [yY] ]] && { log_info "Aborted"; exit 0; }
# Delete files
local deleted=0
local failed=0
for file in "${all_files[@]}"; do
if sudo rm -f "$file" 2>/dev/null; then
((deleted++)) || true
else
((failed++)) || true
log_error "Failed to delete: $file"
fi
done
echo
if [[ $failed -eq 0 ]]; then
log_success "Successfully deleted $deleted file(s), freed ${total_mb} MB"
else
log_warn "Deleted $deleted file(s), failed $failed file(s)"
fi
# Ask if user wants to delete main log files as well
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Main Log Files"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
# Collect existing main log files
local -a main_logs=()
local main_total_size=0
for log in "${log_paths[@]}"; do
if sudo test -f "$log" 2>/dev/null || [[ -f "$log" ]]; then
main_logs+=("$log")
local log_size
log_size=$(sudo stat -c%s "$log" 2>/dev/null || sudo stat -f%z "$log" 2>/dev/null || echo 0)
if [[ "$log_size" =~ ^[0-9]+$ ]]; then
((main_total_size += log_size)) || true
fi
fi
done
if [[ ${#main_logs[@]} -eq 0 ]]; then
log_info "No main log files found"
else
echo "Main log files:"
for log in "${main_logs[@]}"; do
echo " • $log"
done
echo
local main_mb
main_mb=$(awk "BEGIN {printf \"%.2f\", $main_total_size / 1024 / 1024}")
log_warn "Total: ${#main_logs[@]} file(s), ${main_mb} MB"
echo
read -rp "Delete main log files as well? (y/N): " confirm_main
if [[ "$confirm_main" == [yY] ]]; then
local main_deleted=0
local main_failed=0
for log in "${main_logs[@]}"; do
if sudo rm -f "$log" 2>/dev/null; then
((main_deleted++)) || true
else
((main_failed++)) || true
log_error "Failed to delete: $log"
fi
done
echo
if [[ $main_failed -eq 0 ]]; then
log_success "Successfully deleted $main_deleted main log file(s), freed ${main_mb} MB"
else
log_warn "Deleted $main_deleted main log file(s), failed $main_failed file(s)"
fi
else
log_info "Main log files kept intact"
fi
fi
}
# Tar rotated log files
tar_logs() {
local rotate_name="$1"
local target_path="${2:-}"
if [[ -z "$rotate_name" ]]; then
read -rp "Enter rotation config name: " rotate_name
fi
validate_rotate_name "$rotate_name" || exit 1
local config_path="$ROTATE_DIR/$rotate_name"
if [[ ! -f "$config_path" ]]; then
log_error "Configuration not found: $config_path"
exit 1
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Archive Log Files for: $rotate_name"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
# Determine target file path
local tar_file
if [[ -z "$target_path" ]]; then
# Default: current directory
tar_file="$(pwd)/${rotate_name}.tar.gz"
elif [[ -d "$target_path" ]]; then
# Directory provided, append filename
tar_file="${target_path%/}/${rotate_name}.tar.gz"
else
# Full path provided
tar_file="$target_path"
fi
# Check if target file already exists
if [[ -f "$tar_file" ]]; then
log_warn "Target file already exists: $tar_file"
read -rp "Overwrite? (y/N): " confirm
[[ "$confirm" != [yY] ]] && { log_info "Aborted"; exit 0; }
fi
# Verify target directory is writable
local tar_dir
tar_dir=$(dirname "$tar_file")
if [[ ! -d "$tar_dir" ]]; then
log_error "Target directory does not exist: $tar_dir"
exit 1
fi
if [[ ! -w "$tar_dir" ]]; then
log_error "Target directory is not writable: $tar_dir"
exit 1
fi
# Get all log paths
local -a log_paths=()
while IFS= read -r log; do
[[ -n "$log" && "$log" != "{" ]] && log_paths+=("$log")
done < <(awk '
/^[^#]/ && !found_brace {
line = line " " $0
if ($0 ~ /{/) {
found_brace = 1
gsub(/{/, "", line)
n = split(line, words)
for (i = 1; i <= n; i++) {
if (words[i] !~ /^#/ && words[i] != "") {
print words[i]
}
}
}
}
' "$config_path")
if [[ ${#log_paths[@]} -eq 0 ]]; then
log_error "No log paths found in configuration"
exit 1
fi
# Collect all log files (including main log and rotated files)
local -a all_files=()
local total_size=0
for log in "${log_paths[@]}"; do
# Check if main log file exists
if ! sudo test -f "$log" 2>/dev/null && [[ ! -f "$log" ]]; then
log_warn "Log file not found: $log"
continue
fi
local log_dir
local log_base
log_dir=$(dirname "$log")
log_base=$(basename "$log")
# Find all log files (including main and rotated)
while IFS= read -r -d '' log_file; do
if sudo test -f "$log_file" 2>/dev/null; then
all_files+=("$log_file")
# Get file size
local file_size
file_size=$(sudo stat -c%s "$log_file" 2>/dev/null || sudo stat -f%z "$log_file" 2>/dev/null || echo 0)
if [[ "$file_size" =~ ^[0-9]+$ ]]; then
((total_size += file_size)) || true
fi
fi
done < <(sudo find "$log_dir" -maxdepth 1 -type f -name "${log_base}*" -print0 2>/dev/null)
done
if [[ ${#all_files[@]} -eq 0 ]]; then
log_error "No log files found to archive"
exit 1
fi
# Show statistics
local total_mb
total_mb=$(awk "BEGIN {printf \"%.2f\", $total_size / 1024 / 1024}")
log_info "Files to archive: ${#all_files[@]}"
log_info "Total size: ${total_mb} MB"
log_info "Target: $tar_file"
echo
# Create temporary file list
local file_list
file_list=$(mktemp)
trap 'rm -f "$file_list"' EXIT
printf '%s\n' "${all_files[@]}" > "$file_list"
# Create tar.gz archive
log_info "Creating archive..."
if sudo tar -czf "$tar_file" -T "$file_list" --absolute-names 2>/dev/null; then
# Change owner to current user
sudo chown "$SELF_UID:$SELF_GID" "$tar_file" || {
log_warn "Could not change ownership of archive"
}
# Get archive size
local archive_size
archive_size=$(stat -c%s "$tar_file" 2>/dev/null || stat -f%z "$tar_file" 2>/dev/null || echo 0)
local archive_mb
archive_mb=$(awk "BEGIN {printf \"%.2f\", $archive_size / 1024 / 1024}")
# Calculate compression ratio
local ratio
if [[ $total_size -gt 0 ]]; then
ratio=$(awk "BEGIN {printf \"%.1f\", ($total_size - $archive_size) * 100.0 / $total_size}")
else
ratio="0.0"
fi
echo
log_success "Archive created successfully"
log_info "Archive size: ${archive_mb} MB (${ratio}% compression)"
log_info "Location: $tar_file"
else
log_error "Failed to create archive"
exit 1
fi
}
# Show usage
usage() {
cat <<EOF
Usage: $0 COMMAND [OPTIONS]
Commands:
install [NAME] Install a new logrotate configuration
uninstall [NAME] Remove an existing logrotate configuration
info [NAME] Show details about a configuration
list List all logrotate configurations
test [NAME] Test a configuration without applying it
clean [NAME] Delete all rotated log files for a configuration
tar [NAME] [PATH] Archive all log files to tar.gz (default: ./{NAME}.tar.gz)
Options:
NAME Name of the logrotate configuration
PATH Target path for tar archive (optional)
Examples:
$0 install myapp
$0 info myapp
$0 list
$0 clean myapp
$0 tar myapp
$0 tar myapp /backup/logs.tar.gz
$0 tar myapp /backup/
$0 uninstall myapp
EOF
}
# Main
main() {
local command="${1:-}"
local arg="${2:-}"
local arg2="${3:-}"
case "$command" in
install)
install "$arg"
;;
uninstall)
uninstall "$arg"
;;
info)
info "$arg"
;;
list)
list
;;
test)
test "$arg"
;;
clean)
clean "$arg"
;;
tar)
tar_logs "$arg" "$arg2"
;;
help|--help|-h)
usage
;;
"")
log_error "No command specified"
echo
usage
exit 1
;;
*)
log_error "Unknown command: $command"
echo
usage
exit 1
;;
esac
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment