Files
smy-skills/linux-ssh-operator-skill/scripts/ssh_copy.sh
2026-06-12 17:48:53 +08:00

132 lines
2.4 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'USAGE'
Copy files via scp with consistent options.
Usage:
ssh_copy.sh [options] push HOST LOCAL_PATH REMOTE_PATH
ssh_copy.sh [options] pull HOST REMOTE_PATH LOCAL_PATH
Options:
-u, --user USER Override SSH user (or set REMOTE_USER)
-p, --port PORT SSH port (default: REMOTE_PORT or 22)
-i, --key PATH Identity file (default: REMOTE_KEY)
-r, --recursive Copy directories recursively
--accept-new Set StrictHostKeyChecking=accept-new
--dry-run Print the scp command that would run
-h, --help Show help
Environment defaults:
REMOTE_USER, REMOTE_PORT, REMOTE_KEY
Examples:
ssh_copy.sh push my-server ./app.tar.gz /tmp/app.tar.gz
ssh_copy.sh --user ubuntu pull 10.0.0.1 /var/log/syslog ./syslog
USAGE
}
port="${REMOTE_PORT:-22}"
user="${REMOTE_USER:-}"
key="${REMOTE_KEY:-}"
recursive=false
accept_new=false
dry_run=false
while [[ $# -gt 0 ]]; do
case "$1" in
-u|--user)
user="${2:-}"
shift 2
;;
-p|--port)
port="${2:-}"
shift 2
;;
-i|--key)
key="${2:-}"
shift 2
;;
-r|--recursive)
recursive=true
shift
;;
--accept-new)
accept_new=true
shift
;;
--dry-run)
dry_run=true
shift
;;
-h|--help)
usage
exit 0
;;
-*)
echo "Unknown option: $1" >&2
usage >&2
exit 2
;;
*)
break
;;
esac
done
if [[ $# -lt 4 ]]; then
usage >&2
exit 2
fi
direction="$1"
shift
host="$1"
shift
dest_host="$host"
if [[ -n "$user" ]]; then
host_no_user="${host#*@}"
dest_host="${user}@${host_no_user}"
fi
scp_opts=(-P "$port" -p)
if [[ -n "$key" ]]; then
scp_opts+=(-i "$key" -o "IdentitiesOnly=yes")
fi
if $recursive; then
scp_opts+=(-r)
fi
if $accept_new; then
scp_opts+=(-o "StrictHostKeyChecking=accept-new")
fi
case "$direction" in
push)
local_path="$1"
remote_path="$2"
full_cmd=(scp "${scp_opts[@]}" "$local_path" "${dest_host}:${remote_path}")
;;
pull)
remote_path="$1"
local_path="$2"
full_cmd=(scp "${scp_opts[@]}" "${dest_host}:${remote_path}" "$local_path")
;;
*)
echo "Unknown direction: $direction (expected: push|pull)" >&2
usage >&2
exit 2
;;
esac
if $dry_run; then
printf '%q ' "${full_cmd[@]}"
printf '\n'
exit 0
fi
"${full_cmd[@]}"