跨服務器的數據自動化下載
- 功能介紹:
- 上代碼:
發現好久沒寫csdn了,說多了都是淚~~
以后會更新一些自動化工作的腳本or 小tricks,歡迎交流。分享一個最近在業務上寫的較為實用的自動化腳本,可以批量從遠端服務器下載指定數據到當前程序運行服務器,無需每次都輸入密碼,通過集成安裝公鑰的功能,實現免密下載。這個方式適合這種不能安裝 sshpass又想全自動化的環境。
功能介紹:
第一次運行:會提示輸入一次遠端 服務器 的密碼(安裝公鑰)。安裝完成后立即用免密下載。
以后運行:直接免密下載,全自動。
后續所有下載腳本全自動化,不用再輸入任何密碼,也不依賴額外工具。
以從遠端服務器(賬戶:abc)下載數據為例。
上代碼:
#!/usr/bin/env python3
import sys
import os
import subprocess
import tempfile
import shutildef check_key_auth(remote_username, remote_host, private_key_path):"""檢查是否已配置免密"""result = subprocess.run(['ssh', '-i', private_key_path, '-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=no',f'{remote_username}@{remote_host}', 'echo ok'],stdout=subprocess.PIPE, stderr=subprocess.PIPE)return result.returncode == 0def install_pubkey(remote_username, remote_host, private_key_path):"""將本地公鑰寫入遠端 authorized_keys(會要求輸入密碼一次)"""pubkey_path = private_key_path + '.pub'if not os.path.exists(pubkey_path):print(f"未找到公鑰文件 {pubkey_path}")return Falsewith open(pubkey_path, 'r') as f:pubkey_content = f.read().strip()print(f"正在將公鑰寫入 {remote_host},需要輸入 {remote_username} 的密碼...")cmd = ['ssh', f'{remote_username}@{remote_host}',f'mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo "{pubkey_content}" >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys']return subprocess.run(cmd).returncode == 0def download_files_batch(remote_username, remote_host, private_key_path, files_to_download):"""批量下載實現:1. 在本地創建一個臨時目錄 tmpdir2. 用 single scp 命令把所有 remote:files 下載到 tmpdir(scp 支持多個 source + 單個 destination directory)3. 將 tmpdir 下的文件移動到各自的目標位置"""# 先保證目標本地目錄存在(創建父目錄)for _, local_path in files_to_download:os.makedirs(os.path.dirname(local_path), exist_ok=True)tmpdir = tempfile.mkdtemp(prefix='download_')try:# 構造 scp 命令:scp -i key user@host:/path/to/file1 user@host:/path/to/file2 ... <tmpdir>scp_cmd = ['scp', '-i', private_key_path, '-o', 'StrictHostKeyChecking=no']for remote_path, _ in files_to_download:scp_cmd.append(f'{remote_username}@{remote_host}:{remote_path}')scp_cmd.append(tmpdir) # scp 要求最后是目標目錄print("執行 scp,目標臨時目錄:", tmpdir)print("scp 命令:", ' '.join(scp_cmd))proc = subprocess.run(scp_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)if proc.returncode != 0:print("批量 scp 失敗,錯誤信息:")print(proc.stderr.decode(errors='ignore'))return False# scp 成功,把文件從 tmpdir 移動到最終位置for remote_path, local_path in files_to_download:fname = os.path.basename(remote_path)src = os.path.join(tmpdir, fname)if not os.path.exists(src):print(f"警告:遠端文件 {remote_path} 未被下載到臨時目錄({src} 不存在)")# 繼續處理其它文件continueshutil.move(src, local_path)print(f"已移動:{src} -> {local_path}")print("全部文件處理完成。")return Truefinally:# 清理臨時目錄(如果里面還有剩余文件,會一并刪除)try:shutil.rmtree(tmpdir)except Exception as e:print("清理臨時目錄時出錯:", e)def main():if len(sys.argv) != 2:print("用法: python fully_auto_download.py <date>")sys.exit(1)date = sys.argv[1]remote_host = "" ##你需要獲取數據的遠端ipremote_username = "abc"private_key_path = '/.ssh/id_rsa'files_to_download = [(f"/data/{date[:4]}/{date}_000000_000000.csv",f"/save/{date}_000000_000000.csv"),## 此處省略其他需要下載的數據]# 檢查免密if not check_key_auth(remote_username, remote_host, private_key_path):print("未檢測到免密,開始安裝公鑰...")if not install_pubkey(remote_username, remote_host, private_key_path):print("公鑰安裝失敗,請檢查密碼是否正確或遠端權限設置。")sys.exit(1)if not check_key_auth(remote_username, remote_host, private_key_path):print("免密配置仍然失敗,請手動檢查。")sys.exit(1)print("免密配置成功!")# 一次性批量下載ok = download_files_batch(remote_username, remote_host, private_key_path, files_to_download)if not ok:print("批量下載出現問題,退回逐個下載嘗試。")# 如果批量下載失敗,可以回退到逐個 scp(免密已經配置好了,不會再要求密碼)for remote_path, local_path in files_to_download:try:os.makedirs(os.path.dirname(local_path), exist_ok=True)scp_cmd = ['scp', '-i', private_key_path, '-o', 'StrictHostKeyChecking=no',f'{remote_username}@{remote_host}:{remote_path}', local_path]subprocess.run(scp_cmd, check=True)print(f"下載成功: {local_path}")except subprocess.CalledProcessError as e:print(f"下載失敗: {local_path}, 錯誤: {e}")if __name__ == "__main__":main()