diff --git a/linux-ssh-operator-skill/SKILL.md b/linux-ssh-operator-skill/SKILL.md index 56a239f..6f6d502 100644 --- a/linux-ssh-operator-skill/SKILL.md +++ b/linux-ssh-operator-skill/SKILL.md @@ -1,13 +1,14 @@ --- name: linux-ssh-operator-skill -description: 通过 SSH 连接并操作 Linux 服务器:执行远程命令、查看日志、管理 systemd 服务、传输文件(scp/rsync)、配置 SSH 别名、安装公钥启用免密登录、排障。用户提到 ssh/scp/rsync、远程服务器 IP:端口、配置 ssh 别名、ssh-copy-id、免密登录、systemctl/journalctl、部署到服务器、在服务器上运行命令、远程拷贝文件 等场景时使用。 +description: 通过 SSH 连接并操作 Linux 服务器:执行远程命令、查看日志、管理 systemd 服务、传输文件(scp/rsync)、配置 SSH 别名、安装公钥启用免密登录、SSH 隧道/端口转发、跳板机、内网穿透、排障。用户提到 ssh/scp/rsync、远程服务器 IP:端口、配置 ssh 别名、ssh-copy-id、免密登录、systemctl/journalctl、部署到服务器、在服务器上运行命令、远程拷贝文件、SSH 隧道、端口转发、跳板机、堡垒机、服务器上看一下、帮我连上服务器、查看服务器日志 等场景时使用。 + --- # Linux SSH Operator ## Overview -Use SSH to connect to Linux servers and perform safe, repeatable remote operations (commands, logs, services, file transfer, alias bootstrap, passwordless login). +Use SSH to connect to Linux servers and perform safe, repeatable remote operations (commands, logs, services, file transfer, alias bootstrap, passwordless login, tunnels). ## Workflow @@ -99,29 +100,85 @@ ssh -tt my-server sudo systemctl status nginx --no-pager ```bash ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_run.sh my-server -- uname -a ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_run.sh --tty --sudo my-server -- systemctl restart nginx +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_run.sh --compress my-server -- cat /var/log/big.log ``` ### Transfer files -Upload: +Upload (scp): ```bash ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh push my-server ./local.txt /tmp/local.txt ``` -Download: +Download (scp): ```bash ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh pull my-server /var/log/syslog ./syslog ``` +Incremental sync (rsync — preferred for directories or large files): + +```bash +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh --rsync push my-server ./dist/ /var/www/html/ +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh --rsync --delete push my-server ./dist/ /var/www/html/ +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh --rsync pull my-server /var/log/ ./logs/ +``` + +### SSH Tunneling / Port Forwarding + +Local forward (access remote service on a local port): + +```bash +# Access remote MySQL (3306) at localhost:13306 +ssh -L 13306:127.0.0.1:3306 my-server -N +``` + +Remote forward (expose a local port on the server): + +```bash +# Make local :8080 accessible on server's :18080 +ssh -R 18080:127.0.0.1:8080 my-server -N +``` + +Jump host (bastion → target): + +```bash +ssh -J bastion-user@bastion:22 target-user@target-host +``` + +Or configure in `~/.ssh/config`: + +```sshconfig +Host target-internal + HostName 10.0.0.50 + User ubuntu + ProxyJump bastion +``` + +### SSH Multiplexing (faster repeated connections) + +Add to `~/.ssh/config` to reuse the same TCP connection: + +```sshconfig +Host * + ControlMaster auto + ControlPath ~/.ssh/ctrl-%h-%p-%r + ControlPersist 60s +``` + +The first `ssh my-server` opens a master connection; subsequent connections reuse it without re-handshaking. + ## Common Ops (snippets) - Disk: `df -h`, `du -sh /path/* | sort -h` - Memory/CPU: `free -h`, `top`, `ps aux --sort=-%mem | head` - Logs: `journalctl -u SERVICE -n 200 --no-pager`, `tail -n 200 -f /path/log` -- Services: `systemctl status|restart|stop SERVICE` +- Services: `systemctl status|restart|stop|enable SERVICE` - Networking: `ss -lntp`, `ip a`, `ip r`, `curl -v http://127.0.0.1:PORT/` +- Docker: `docker ps`, `docker logs -f CONTAINER`, `docker exec -it CONTAINER bash` +- Config test: `nginx -t`, `sshd -T` +- Open files: `lsof -i :PORT`, `fuser PORT/tcp` ## Safety @@ -136,5 +193,5 @@ Download: ## Scripts - `scripts/ssh_alias_setup.sh`: create/update SSH aliases and optionally run `ssh-copy-id`. -- `scripts/ssh_run.sh`: run remote commands with consistent options. -- `scripts/ssh_copy.sh`: push/pull files via scp with consistent options. +- `scripts/ssh_run.sh`: run remote commands with consistent options (supports `--compress`, `--tty`, `--sudo`). +- `scripts/ssh_copy.sh`: push/pull files via scp or rsync (use `--rsync` for incremental transfers). diff --git a/linux-ssh-operator-skill/SKILL.zh-CN.md b/linux-ssh-operator-skill/SKILL.zh-CN.md index 8c22616..d64a8af 100644 --- a/linux-ssh-operator-skill/SKILL.zh-CN.md +++ b/linux-ssh-operator-skill/SKILL.zh-CN.md @@ -1,6 +1,7 @@ --- name: linux-ssh-operator-skill -description: 通过 SSH 连接并操作 Linux 服务器:执行远程命令、查看日志、管理 systemd 服务、传输文件(scp/rsync)、配置 SSH 别名、安装公钥启用免密登录、排障。用户提到 ssh/scp/rsync、远程服务器 IP:端口、配置 ssh 别名、ssh-copy-id、免密登录、systemctl/journalctl、部署到服务器、在服务器上运行命令、远程拷贝文件 等场景时使用。 +description: 通过 SSH 连接并操作 Linux 服务器:执行远程命令、查看日志、管理 systemd 服务、传输文件(scp/rsync)、配置 SSH 别名、安装公钥启用免密登录、SSH 隧道/端口转发、跳板机、内网穿透、排障。用户提到 ssh/scp/rsync、远程服务器 IP:端口、配置 ssh 别名、ssh-copy-id、免密登录、systemctl/journalctl、部署到服务器、在服务器上运行命令、远程拷贝文件、SSH 隧道、端口转发、跳板机、堡垒机、服务器上看一下、帮我连上服务器、查看服务器日志 等场景时使用。 + --- # Linux SSH 运维助手(中文说明) @@ -14,9 +15,10 @@ description: 通过 SSH 连接并操作 Linux 服务器:执行远程命令、 - 执行远程命令 - 查看系统与服务日志 - 管理 `systemd` 服务 -- 上传和下载文件 +- 上传和下载文件(scp 或 rsync) - 配置 SSH 别名 - 安装公钥并启用免密登录 +- SSH 隧道 / 端口转发 / 跳板机 - 进行常见运维排障 适合以下场景: @@ -25,9 +27,11 @@ description: 通过 SSH 连接并操作 Linux 服务器:执行远程命令、 - 在服务器上运行命令 - 查看 `journalctl` / 应用日志 - 启动、停止、重启服务 -- 把文件部署到服务器 +- 把文件部署到服务器(scp 或 rsync 增量同步) - 从服务器拉取日志、配置或产物文件 -- 按“别名 + IP + 密码”快速配置一键 SSH 免密登录 +- 按"别名 + IP + 密码"快速配置一键 SSH 免密登录 +- 配置端口转发访问内网服务 +- 通过跳板机/堡垒机连接内网服务器 ## 工作流程 @@ -71,7 +75,7 @@ ssh my-server ### 一键配置别名 + 免密登录 -当用户提供“别名、主机/IP、密码”,并希望直接通过 `ssh 别名` 登录时,优先使用下面的流程: +当用户提供"别名、主机/IP、密码",并希望直接通过 `ssh 别名` 登录时,优先使用下面的流程: 1. 使用辅助脚本写入或更新 SSH 别名: @@ -118,22 +122,78 @@ ssh -tt my-server sudo systemctl status nginx --no-pager ```bash ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_run.sh my-server -- uname -a ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_run.sh --tty --sudo my-server -- systemctl restart nginx +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_run.sh --compress my-server -- cat /var/log/big.log ``` ### 传输文件 -上传文件: +上传文件(scp): ```bash ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh push my-server ./local.txt /tmp/local.txt ``` -下载文件: +下载文件(scp): ```bash ~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh pull my-server /var/log/syslog ./syslog ``` +增量同步(rsync,推荐用于目录或大文件): + +```bash +# 上传目录 +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh --rsync push my-server ./dist/ /var/www/html/ +# 上传并删除远端多余文件 +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh --rsync --delete push my-server ./dist/ /var/www/html/ +# 下载目录 +~/.claude/skills/linux-ssh-operator-skill/scripts/ssh_copy.sh --rsync pull my-server /var/log/ ./logs/ +``` + +### SSH 隧道 / 端口转发 + +本地转发(将远程服务映射到本地端口): + +```bash +# 把远程 MySQL(3306) 映射到本地 13306 +ssh -L 13306:127.0.0.1:3306 my-server -N +``` + +远程转发(将本地服务暴露到服务器端口): + +```bash +# 把本地 :8080 映射到服务器 :18080 +ssh -R 18080:127.0.0.1:8080 my-server -N +``` + +跳板机 / 堡垒机: + +```bash +ssh -J bastion-user@bastion:22 target-user@target-host +``` + +或在 `~/.ssh/config` 中配置: + +```sshconfig +Host target-internal + HostName 10.0.0.50 + User ubuntu + ProxyJump bastion +``` + +### SSH 多路复用(加速重复连接) + +在 `~/.ssh/config` 中添加,复用同一 TCP 连接: + +```sshconfig +Host * + ControlMaster auto + ControlPath ~/.ssh/ctrl-%h-%p-%r + ControlPersist 60s +``` + +第一次 `ssh my-server` 建立主连接,后续连接直接复用,无需重新握手,速度更快。 + ## 常见运维操作 - 磁盘空间:`df -h` @@ -142,8 +202,11 @@ ssh -tt my-server sudo systemctl status nginx --no-pager - 进程查看:`ps aux --sort=-%mem | head` - 日志查看:`journalctl -u SERVICE -n 200 --no-pager` - 日志跟踪:`tail -n 200 -f /path/log` -- 服务管理:`systemctl status|restart|stop SERVICE` +- 服务管理:`systemctl status|restart|stop|enable SERVICE` - 网络排查:`ss -lntp`、`ip a`、`ip r`、`curl -v http://127.0.0.1:PORT/` +- Docker:`docker ps`、`docker logs -f CONTAINER`、`docker exec -it CONTAINER bash` +- 配置测试:`nginx -t`、`sshd -T` +- 端口占用:`lsof -i :PORT`、`fuser PORT/tcp` ## 安全注意事项 @@ -170,7 +233,8 @@ ssh -tt my-server sudo systemctl status nginx --no-pager - 指定用户、端口、私钥 - 设置连接超时 -- 启用 TTY +- 启用 TTY(`--tty`) +- 启用 SSH 压缩(`--compress`,适合慢速链路) - 使用 `sudo` 或 `sudo -n` - 使用 `--accept-new` 处理首次连接主机 - 使用 `--dry-run` 预览实际将执行的命令 @@ -184,11 +248,13 @@ ssh -tt my-server sudo systemctl status nginx --no-pager ### `scripts/ssh_copy.sh` -用于通过 `scp` 上传或下载文件,支持: +用于通过 `scp` 或 `rsync` 上传或下载文件,支持: - `push` 上传文件到远程服务器 - `pull` 从远程服务器下载文件 -- 递归复制目录 +- `--rsync`:使用 rsync 增量同步(显示进度,适合目录和大文件) +- `--delete`:配合 `--rsync push` 删除远端多余文件 +- 递归复制目录(scp 模式用 `-r`) - 指定用户、端口、私钥 - 使用 `--accept-new` - 使用 `--dry-run` 预览命令 diff --git a/linux-ssh-operator-skill/references/ssh-playbook.md b/linux-ssh-operator-skill/references/ssh-playbook.md index 702e0d3..c59d969 100644 --- a/linux-ssh-operator-skill/references/ssh-playbook.md +++ b/linux-ssh-operator-skill/references/ssh-playbook.md @@ -60,6 +60,7 @@ ssh my-server "du -sh /var/log/* | sort -h | tail" ```bash ssh my-server "ps aux --sort=-%mem | head" ssh my-server "ss -lntp" +ssh my-server "lsof -i :8080" ``` ### Logs (systemd) @@ -67,6 +68,7 @@ ssh my-server "ss -lntp" ```bash ssh my-server "journalctl -u SERVICE -n 200 --no-pager" ssh my-server "journalctl -u SERVICE -f --no-pager" +ssh my-server "journalctl -u SERVICE --since '1 hour ago' --no-pager" ``` ### Services (systemd) @@ -89,15 +91,137 @@ Non-interactive sudo (fails if a password prompt would be required): ssh my-server "sudo -n systemctl restart SERVICE" ``` +### Docker + +```bash +ssh my-server "docker ps" +ssh my-server "docker logs --tail=200 -f CONTAINER" +ssh my-server "docker exec -it CONTAINER bash" +ssh my-server "docker stats --no-stream" +``` + +### File editing shortcuts + +```bash +# View a config file +ssh my-server "cat /etc/nginx/nginx.conf" + +# Quick in-place line replacement +ssh my-server "sed -i 's/old/new/g' /path/to/file" + +# Append a line +ssh my-server "echo 'new line' >> /path/to/file" +``` + +## SSH Tunneling / Port Forwarding + +### Local forward + +Access a remote service on a local port (server-side port does not need to be publicly open): + +```bash +# remote MySQL → localhost:13306 +ssh -L 13306:127.0.0.1:3306 my-server -N + +# remote Redis → localhost:16379 +ssh -L 16379:127.0.0.1:6379 my-server -N +``` + +Add `-f` to background the tunnel: + +```bash +ssh -fNL 13306:127.0.0.1:3306 my-server +``` + +### Remote forward + +Expose a local service on the server (useful for demos or webhooks): + +```bash +# local :8080 → server :18080 +ssh -R 18080:127.0.0.1:8080 my-server -N +``` + +### Jump host / bastion + +```bash +# Single jump +ssh -J bastion user@target + +# Multi-hop +ssh -J jump1,jump2 user@target +``` + +`~/.ssh/config` version: + +```sshconfig +Host target-internal + HostName 10.0.0.50 + User ubuntu + ProxyJump bastion +``` + +## SSH Multiplexing + +Reuse the same TCP connection for multiple SSH sessions — avoids repeated handshakes: + +```sshconfig +Host * + ControlMaster auto + ControlPath ~/.ssh/ctrl-%h-%p-%r + ControlPersist 60s +``` + +Check active master sockets: + +```bash +ls ~/.ssh/ctrl-* +``` + +Close a master socket manually: + +```bash +ssh -O exit my-server +``` + ## Safer host key handling - Prefer verifying the host key fingerprint out-of-band on first connect. - If you must automate first-connect for ephemeral hosts, use `StrictHostKeyChecking=accept-new` (OpenSSH 7.6+). - If you see a "host key changed" warning, treat it as a potential security incident until you confirm the change is expected. +Remove a stale known_hosts entry: + +```bash +ssh-keygen -R SERVER_IP +``` + ## Troubleshooting quick hits -- `Permission denied (publickey)`: wrong user, wrong key, server missing your public key, or `sshd` settings. -- `Connection timed out`: routing/firewall/security group, wrong port, server down. -- `No route to host`: network path missing (VPN, subnet, ACL). +| Symptom | Likely cause | Fix | +|---|---|---| +| `Permission denied (publickey)` | Wrong user/key, pub key not on server, sshd config | Check `~/.ssh/authorized_keys` on server; verify key matches | +| `Connection timed out` | Firewall/security group, wrong port, server down | Check port, security group, ping | +| `No route to host` | Network path missing (VPN, ACL, subnet) | Check VPN, routing table | +| `Host key changed` warning | Server rebuilt, or MITM | Verify with out-of-band channel; `ssh-keygen -R HOST` if expected | +| `Too many authentication failures` | SSH agent offering too many keys | Use `-o IdentitiesOnly=yes -i ~/.ssh/id_ed25519` | +| `sudo: a terminal is required` | No TTY allocated | Use `ssh -tt` or pass `-t` to wrapper | +### Debug connection verbosely + +```bash +ssh -vvv my-server +``` + +### Check sshd config on server + +```bash +ssh my-server "sudo sshd -T | grep -E 'pubkeyauthentication|passwordauthentication|permitrootlogin'" +``` + +### Check authorized_keys permissions (common cause of publickey failure) + +```bash +ssh my-server "ls -la ~/.ssh/ && cat ~/.ssh/authorized_keys" +# .ssh should be 700, authorized_keys should be 600 +``` diff --git a/linux-ssh-operator-skill/scripts/ssh_alias_setup.sh b/linux-ssh-operator-skill/scripts/ssh_alias_setup.sh index 90519b2..3234a8f 100644 --- a/linux-ssh-operator-skill/scripts/ssh_alias_setup.sh +++ b/linux-ssh-operator-skill/scripts/ssh_alias_setup.sh @@ -118,7 +118,7 @@ if [[ ! -f "$key" ]]; then fi fi -if [[ ! -f "$key_pub" ]]; then +if ! $dry_run && [[ ! -f "$key_pub" ]]; then echo "Public key not found: $key_pub" >&2 exit 1 fi diff --git a/linux-ssh-operator-skill/scripts/ssh_copy.sh b/linux-ssh-operator-skill/scripts/ssh_copy.sh index a646c64..a218fa8 100644 --- a/linux-ssh-operator-skill/scripts/ssh_copy.sh +++ b/linux-ssh-operator-skill/scripts/ssh_copy.sh @@ -3,7 +3,7 @@ set -euo pipefail usage() { cat <<'USAGE' -Copy files via scp with consistent options. +Copy files via scp or rsync with consistent options. Usage: ssh_copy.sh [options] push HOST LOCAL_PATH REMOTE_PATH @@ -13,9 +13,11 @@ 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 + -r, --recursive Copy directories recursively (scp mode only; rsync always recurses) + --rsync Use rsync instead of scp (incremental, shows progress) + --delete With --rsync push: delete remote files not present in source --accept-new Set StrictHostKeyChecking=accept-new - --dry-run Print the scp command that would run + --dry-run Print the command that would run -h, --help Show help Environment defaults: @@ -23,6 +25,8 @@ Environment defaults: Examples: ssh_copy.sh push my-server ./app.tar.gz /tmp/app.tar.gz + ssh_copy.sh --rsync push my-server ./dist/ /var/www/html/ + ssh_copy.sh --rsync --delete push my-server ./dist/ /var/www/html/ ssh_copy.sh --user ubuntu pull 10.0.0.1 /var/log/syslog ./syslog USAGE } @@ -32,47 +36,28 @@ user="${REMOTE_USER:-}" key="${REMOTE_KEY:-}" recursive=false +use_rsync=false +delete_mode=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 - ;; + -u|--user) user="${2:-}"; shift 2 ;; + -p|--port) port="${2:-}"; shift 2 ;; + -i|--key) key="${2:-}"; shift 2 ;; + -r|--recursive) recursive=true; shift ;; + --rsync) use_rsync=true; shift ;; + --delete) delete_mode=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 - ;; + *) break ;; esac done @@ -81,11 +66,8 @@ if [[ $# -lt 4 ]]; then exit 2 fi -direction="$1" -shift - -host="$1" -shift +direction="$1"; shift +host="$1"; shift dest_host="$host" if [[ -n "$user" ]]; then @@ -93,34 +75,70 @@ if [[ -n "$user" ]]; then 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 +if $use_rsync; then + if ! command -v rsync >/dev/null 2>&1; then + echo "rsync is required but not installed." >&2 + exit 1 + fi + ssh_parts=("ssh" "-p" "$port") + if [[ -n "$key" ]]; then + ssh_parts+=("-i" "$key" "-o" "IdentitiesOnly=yes") + fi + if $accept_new; then + ssh_parts+=("-o" "StrictHostKeyChecking=accept-new") + fi + rsync_opts=(-avz --progress -e "${ssh_parts[*]}") -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 + case "$direction" in + push) + local_path="$1" + remote_path="$2" + if $delete_mode; then + rsync_opts+=(--delete) + fi + full_cmd=(rsync "${rsync_opts[@]}" "$local_path" "${dest_host}:${remote_path}") + ;; + pull) + remote_path="$1" + local_path="$2" + full_cmd=(rsync "${rsync_opts[@]}" "${dest_host}:${remote_path}" "$local_path") + ;; + *) + echo "Unknown direction: $direction (expected: push|pull)" >&2 + usage >&2 + exit 2 + ;; + esac +else + 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 +fi if $dry_run; then printf '%q ' "${full_cmd[@]}" diff --git a/linux-ssh-operator-skill/scripts/ssh_run.sh b/linux-ssh-operator-skill/scripts/ssh_run.sh index 2ec38da..94f0f4d 100644 --- a/linux-ssh-operator-skill/scripts/ssh_run.sh +++ b/linux-ssh-operator-skill/scripts/ssh_run.sh @@ -14,6 +14,7 @@ Options: -p, --port PORT SSH port (default: REMOTE_PORT or 22) -i, --key PATH Identity file (default: REMOTE_KEY) -t, --tty Force pseudo-tty allocation (useful for sudo prompts) + -C, --compress Enable SSH compression (useful on slow links) --accept-new Set StrictHostKeyChecking=accept-new --sudo Prefix command with sudo -- --sudo-non-interactive Prefix command with sudo -n -- (fails if password needed) @@ -36,6 +37,7 @@ key="${REMOTE_KEY:-}" connect_timeout="${REMOTE_CONNECT_TIMEOUT:-10}" tty=false +compress=false accept_new=false sudo_mode="" dry_run=false @@ -58,6 +60,10 @@ while [[ $# -gt 0 ]]; do tty=true shift ;; + -C|--compress) + compress=true + shift + ;; --accept-new) accept_new=true shift @@ -126,14 +132,15 @@ if $accept_new; then ssh_opts+=(-o "StrictHostKeyChecking=accept-new") fi +if $compress; then + ssh_opts+=(-C) +fi + if $tty; then ssh_opts+=(-tt) fi cmd=("$@") -if [[ ${#cmd[@]} -gt 0 && "${cmd[0]}" == "--" ]]; then - cmd=("${cmd[@]:1}") -fi if [[ -n "$sudo_mode" && ${#cmd[@]} -gt 0 ]]; then if [[ "$sudo_mode" == "sudo-n" ]]; then cmd=("sudo" "-n" "--" "${cmd[@]}")