每次登录远程服务器后手动上传下载文件,就像用勺子转移游泳池的水——效率低到让人抓狂。作为运维老鸟,我习惯在SSH连接后直接调用SCP完成文件传输,这种组合拳能节省80%的文件操作时间。今天就来拆解这套工作流中的核心技巧和避坑指南。
先确保本地与远程主机已配置SSH免密登录:
bash复制# 生成密钥对(如果已有可跳过)
ssh-keygen -t rsa -b 4096
# 将公钥上传到远程主机
ssh-copy-id user@remote_host
注意:如果远程主机使用非标准SSH端口(如2222),需要加上-p参数:
ssh-copy-id -p 2222 user@remote_host
绝大多数Linux发行版已内置SCP工具,验证安装:
bash复制which scp # 应返回/usr/bin/scp类似路径
若未安装,可通过包管理器快速安装:
bash复制# Ubuntu/Debian
sudo apt install openssh-client
# CentOS/RHEL
sudo yum install openssh-clients
从本地向远程服务器传文件:
bash复制scp /local/path/file.txt user@remote_host:/remote/path/
从远程服务器下载文件到本地:
bash复制scp user@remote_host:/remote/path/file.txt /local/path/
递归传输整个目录(含子目录):
bash复制scp -r /local/folder user@remote_host:/remote/path/
限速传输(避免占用全部带宽):
bash复制scp -l 800 /large_file.iso user@remote_host:/remote/ # 限速800Kb/s
保留文件原始属性(权限、时间戳等):
bash复制scp -p config.ini user@remote_host:/etc/app/
指定非标准SSH端口(如2222):
bash复制scp -P 2222 file.txt user@remote_host:/tmp/
启用压缩传输(适合文本文件):
bash复制scp -C log_file.tar.gz user@remote_host:/backups/
遇到"Permission denied"错误时:
bash复制ssh user@remote_host "ls -ld /target/path"
bash复制scp -o 'StrictHostKeyChecking=no' file.txt user@remote_host:/tmp/
大文件传输中断后,推荐改用rsync续传:
bash复制rsync -P --rsh=ssh /local/big_file user@remote_host:/remote/
提示:-P参数显示进度并支持断点续传
文件名含空格或特殊字符时:
bash复制scp "file with spaces.txt" user@remote_host:"/path/with\ spaces/"
或者使用转义字符:
bash复制scp file\ with\ spaces.txt user@remote_host:/normal_path/
bash复制ssh-keygen -t ed25519 -f ~/.ssh/scp_key
code复制Host production_server
HostName 192.168.1.100
User deploy
IdentityFile ~/.ssh/scp_key
Port 2222
之后即可简化命令:
bash复制scp backup.zip production_server:/opt/backups/
检查实际使用的加密算法:
bash复制scp -v file.txt user@remote_host:/tmp/ 2>&1 | grep "ciphers"
推荐在/etc/ssh/sshd_config中强制使用高强度加密:
code复制Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
创建transfer.sh脚本:
bash复制#!/bin/bash
REMOTE="user@remote_host"
LOCAL_DIR="/data/uploads"
for file in $LOCAL_DIR/*.csv; do
scp "$file" "$REMOTE:/incoming/"
if [ $? -eq 0 ]; then
echo "$(date): $file transferred" >> transfer.log
rm "$file"
fi
done
使用GNU parallel加速大量小文件传输:
bash复制find /log_dir -name "*.log" | parallel -j 4 scp {} user@remote_host:/archive/
-j 4参数表示同时运行4个SCP进程
pv工具可视化传输进度:
bash复制tar czf - /data | pv | ssh user@remote_host "tar xzf - -C /backup"
安装pv:sudo apt install pv
| 特性 | SCP | SFTP |
|---|---|---|
| 传输速度 | 更快(单一连接) | 稍慢(多通道) |
| 功能完整性 | 仅文件传输 | 完整文件管理 |
| 断点续传 | 不支持 | 支持 |
| 交互性 | 非交互式 | 交互式 |
需要同步增量变更时,rsync更高效:
bash复制rsync -avz --delete /local/path/ user@remote_host:/remote/path/
参数说明:
每日凌晨3点自动备份数据库:
bash复制#!/bin/bash
BACKUP_FILE="/backups/db_$(date +%Y%m%d).sql.gz"
mysqldump -u root -pPASSWORD --all-databases | gzip > $BACKUP_FILE
scp $BACKUP_FILE backup_user@storage_server:/mysql_backups/
find /backups -type f -mtime +7 -delete
添加到crontab:
bash复制0 3 * * * /path/to/backup_script.sh
从多台服务器收集日志:
bash复制for server in web{1..5}.example.com; do
scp $server:/var/log/nginx/access.log ./logs/${server}_access.log
done
记录所有SCP传输操作:
code复制Subsystem scp /usr/lib/openssh/sftp-server -l INFO -f AUTHPRIV
bash复制echo "authpriv.* /var/log/scp_transfers.log" > /etc/rsyslog.d/scp.conf
systemctl restart rsyslog
调整SSH配置提升传输速度:
bash复制scp -o "Compression=yes" \
-o "IPQoS=throughput" \
-o "ConnectTimeout=10" \
large_file.iso user@remote_host:/data/
当传输大量小文件时,建议:
bash复制tar czf bundle.tar.gz /path/to/files/
scp bundle.tar.gz user@remote_host:/target/
ssh user@remote_host "tar xzf /target/bundle.tar.gz -C /destination/"
bash复制tar cf - /data | zstd -3 | ssh user@remote_host "zstd -d | tar xf - -C /target"
配置SSH连接复用减少认证开销:
在~/.ssh/config中添加:
code复制Host *
ControlMaster auto
ControlPath ~/.ssh/control:%h:%p:%r
ControlPersist 1h
之后首次连接会建立主连接,后续SCP操作复用该连接
在Android手机上使用SCP:
bash复制pkg install openssh
ssh-keygen -t ed25519
cat ~/.ssh/id_ed25519.pub | ssh user@pc "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
bash复制scp -P 8022 /sdcard/DCIM/photo.jpg user@home_pc:/Pictures/
通过Shortcuts实现一键备份相册:
bash复制cd /tmp
find /var/mobile/Media/DCIM -name "IMG_*" -type f -mtime -1 | while read file; do
scp -i ~/.ssh/mobile_key "$file" user@nas:/Photos/
done
通过Git Bash或Windows Subsystem for Linux (WSL)使用SCP:
bash复制# 从Windows上传到Linux
scp 'C:\Users\user\Document\report.docx' user@linux_server:/home/user/
# 路径包含空格时使用双引号
scp "D:\My Documents\data.csv" user@server:/tmp/
处理中文文件名乱码:
bash复制# 客户端配置
echo "SendEnv LANG LC_*" >> ~/.ssh/config
# 服务端配置
echo "AcceptEnv LANG LC_*" >> /etc/ssh/sshd_config
systemctl restart sshd
记录详细的SCP操作日志:
bash复制# 在远程主机上配置
echo "export SCP_LOG_FILE=/var/log/scp_operations.log" >> /etc/profile
echo "scp() { echo \"\$(date +'%Y-%m-%d %T') \$(whoami) \$@\" >> \$SCP_LOG_FILE; /usr/bin/scp \"\$@\"; }" >> /etc/profile
source /etc/profile
使用iftop监控SCP流量:
bash复制sudo iftop -f 'port 22' -nNP
关键指标:
使用gpg加密后再传输敏感数据:
bash复制gpg -c --cipher-algo AES256 secret_data.db
scp secret_data.db.gpg backup_server:/secure_storage/
解密时:
bash复制gpg -d secret_data.db.gpg > secret_data.db
当网络不稳定时:
bash复制split -b 100M large_file.zip large_file_part_
bash复制for part in large_file_part_*; do
while ! scp $part user@remote_host:/tmp/; do
echo "传输失败,10秒后重试..."
sleep 10
done
done
bash复制ssh user@remote_host "cat /tmp/large_file_part_* > /tmp/large_file.zip"
从宿主机复制到容器:
bash复制docker cp local_file.txt container_id:/path/in/container/
反向操作:
bash复制docker cp container_id:/path/to/file /host/path/
通过kubectl cp等效实现SCP功能:
bash复制# 上传到Pod
kubectl cp /local/file pod-name:/container/path -n namespace
# 从Pod下载
kubectl cp pod-name:/container/path/file /local/dest -n namespace
通过跳板机传输到内网服务器:
bash复制scp -o ProxyCommand="ssh -W %h:%p jump_user@jump_host" \
local_file.txt internal_user@internal_host:/target/
使用tee同时传输到多个服务器:
bash复制tar czf - /source_data | tee >(ssh user@server1 "tar xzf - -C /dest1") \
>(ssh user@server2 "tar xzf - -C /dest2") \
| ssh user@server3 "tar xzf - -C /dest3"
推荐工具组合:
bash复制lftp sftp://user:password@host -e "mirror --parallel=3 /remote /local; quit"
bash复制rclone copy /local/dir remote:path --progress --transfers 4
使用screen保持长时间传输:
bash复制screen -S file_transfer
scp -r big_folder user@remote:/backup/
# Ctrl+A then D detach
# 恢复查看:screen -r file_transfer
传输后自动验证文件一致性:
bash复制scp important.dat user@remote:/backup/
ssh user@remote "sha256sum /backup/important.dat" | \
diff - <(sha256sum important.dat) && echo "验证通过"
使用--exclude参数跳过敏感文件:
bash复制scp -r --exclude="*.key" --exclude="*.env" /config_dir/ user@remote:/safe_copy/
在playbook中使用SCP模块:
yaml复制- name: Transfer config files
ansible.builtin.scp:
src: "/local/configs/{{ item }}"
dest: "/etc/app/"
remote_user: "deploy"
loop:
- app.conf
- secrets.ini
在GitLab CI中实现部署:
yaml复制deploy:
stage: deploy
script:
- scp -o StrictHostKeyChecking=no target/*.war deploy@production:/opt/tomcat/webapps/
- ssh deploy@production "systemctl restart tomcat"
根据时间段调整传输速度:
bash复制hour=$(date +%H)
if [ $hour -ge 8 ] && [ $hour -lt 18 ]; then
speed_limit=500 # 工作时间限速500Kb/s
else
speed_limit=5000 # 夜间全速
fi
scp -l $speed_limit large_file.tar.gz user@remote:/backups/
标记SCP流量为低优先级:
bash复制sudo tc qdisc add dev eth0 root handle 1: htb
sudo tc class add dev eth0 parent 1: classid 1:10 htb rate 100mbit prio 3
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip dport 22 0xffff flowid 1:10
当SSH不可用时,使用Python临时HTTP服务:
bash复制# 发送方启动服务
python3 -m http.server 8000
# 接收方下载
curl -O http://sender_ip:8000/file.txt
使用netcat直接传输:
bash复制# 接收方监听
nc -l 1234 > received_file.iso
# 发送方传输
nc receiver_ip 1234 < source_file.iso