将远程服务器文件同步到本地 Windows

这个脚本通过 Plink 连接远程服务器,查找以 daily- 开头文件并将其下载到本地,使用 PSCP 执行文件传输,整个过程完全自动化。脚本的主要功能步骤如下:

  1. 定义服务器和文件路径:指定远程服务器地址、路径和本地存储目录。
  2. 查找文件:使用 Plink 在远程服务器上查找符合条件的文件(例如,文件名以 daily- 开头)。
  3. 文件下载:如果找到目标文件,则使用 PSCP 将其下载到本地。
  4. 删除原文件:下载完成后,使用 Plink 删除远程服务器上的文件。

工具介绍

  • Plink:Plink 是 PuTTY 软件包中的命令行 SSH 客户端,支持通过 SSH 远程执行命令。
  • PSCP:PSCP 是 PuTTY 软件包中的命令行工具,用于通过 SCP 协议从远程服务器传输文件到本地。
@echo off

:: 定义远程服务器和路径
set SRC_SERVER=user@1.2.3.4
set SRC_PATH=/home/user

:: 定义密码
set SRC_PASSWORD="password"

:: 定义本地目标目录
set DEST_DIR=C:\Workspace\

:: 创建目标目录(如果不存在)
mkdir "%DEST_DIR%" 2>nul

:: 使用 plink 检查是否有以 daily- 开头的文件,并获取文件路径
plink -ssh -pw "%SRC_PASSWORD%" -batch %SRC_SERVER% "find %SRC_PATH% -type f -name 'daily-*' | head -n 1" > file_check.txt

:: 读取文件路径
set /p FILE_PATH=<file_check.txt
del file_check.txt

:: 如果文件路径为空,则表示没有找到文件
if "%FILE_PATH%"=="" (
    echo  daily- not exist
    exit /b
)

:: 从远程服务器下载该文件到本地目标目录,并删除远端文件
pscp -pw "%SRC_PASSWORD%" %SRC_SERVER%:%FILE_PATH% %DEST_DIR%\
plink -ssh -pw "%SRC_PASSWORD%" -batch %SRC_SERVER% "rm -rf %FILE_PATH%

在 Windows 7 上使用批处理脚本同步两个远程服务器间的文件

本文介绍一个批处理脚本在两个远程服务器之间同步文件,并且在操作过程中添加时间戳以便后续管理和审计。

1. 设置环境与变量

首先,定义远程服务器的地址和文件路径,同时还要指定本地的临时存储目录。以下是相关变量的设置:

:: 定义远程服务器和路径
set SRC_SERVER=user@a.b.c.d
set SRC_PATH=/SRC_PATH
set DEST_SERVER=user2@1.2.3.4
set DEST_PATH=/DEST_PATH

:: 定义密码
set SRC_PASSWORD="password1"
set DEST_PASSWORD="password2"

:: 临时存储路径
set TEMP_DIR=C:\Users\Administrator\Desktop\remote_sync

这里的 SRC_SERVERDEST_SERVER 分别是源服务器和目标服务器的地址,SRC_PATHDEST_PATH 是对应的文件路径。TEMP_DIR 是用来存放中间文件的本地目录。

2. 创建本地临时目录

在执行文件传输操作前,确保本地有一个临时目录用于存储从源服务器下载的文件:

:: 创建本地临时目录
mkdir "%TEMP_DIR%" 2>nul

这里使用了 2>nul 来忽略错误输出,避免目录已存在时的提示。

3. 生成带有时间戳的目录名

通过 for 循环来提取所需的年月日、时分( Windows 7 的 %date%%time% 和其他系统有区别,如果是 Windows 10 需要自己验证一下):

for /f "tokens=1-6 delims=/:. " %%a in ("%date% %time%") do (
    set "timestamp=%%b%%c%%d_%%e%%f"
)

此代码通过分隔符 /, :, ., 和空格提取年月日时分,最终生成格式如 20240901_1333 的时间戳。

4. 文件传输与清理

接下来,将从源服务器下载的文件传输到目标服务器,并在传输成功后删除源服务器上的文件:

:: 从第一个远程服务器下载文件到本地临时目录
pscp -pw "%SRC_PASSWORD%" -r %SRC_SERVER%:%SRC_PATH%/* %TEMP_DIR%	

:: 将本地临时目录的文件上传到第二个远程服务器
pscp -pw "%DEST_PASSWORD%" -r "%TEMP_DIR%\*" %DEST_SERVER%:%DEST_PATH%

:: 如果上传成功,删除源服务器上的文件
if %ERRORLEVEL%==0 (
    plink -ssh -pw "%SRC_PASSWORD%" -batch %SRC_SERVER% "rm -rf %SRC_PATH%/*"
    echo 已成功删除源服务器上的文件
) else (
    echo 文件传输失败,未删除源服务器上的文件
)

其中,pscp 是 PuTTY 提供的命令行工具,用于执行安全的文件传输操作。plink 则是一个用于执行远程命令的工具。%ERRORLEVEL% 检查上一步操作是否成功,如果成功则删除源服务器上的文件。

5. 归档与日志管理

最后,将本地的临时目录重命名为带时间戳的目录,以便于管理和备份:

:: 移动临时文件夹到带时间戳的目录
move "%TEMP_DIR%" "%TEMP_DIR%_%timestamp%"

echo 文件传输完成

这一步确保每次文件传输操作都有对应的本地备份,便于日后查看或还原。

最终代码

这是目前最新的版本,做了些微调:

@echo off
chcp 65001 >nul

:: 定义远程服务器和路径
set SRC_SERVER=user@a.b.c.d
set SRC_PATH=/SRC_PATH
set DEST_SERVER=user2@1.2.3.4
set DEST_PATH=/DEST_PATH

:: 定义密码
set SRC_PASSWORD="password1"
set DEST_PASSWORD="password2"

:: 临时存储路径
set TEMP_DIR=C:\Users\Administrator\Desktop\remote_sync
:: 获取源服务器的文件数量
plink -ssh -pw "%SRC_PASSWORD%" -batch %SRC_SERVER% "find %SRC_PATH% -type f | wc -l" > file_count.txt
set /p FILE_COUNT=<file_count.txt
del file_count.txt

:: 判断文件数量是否大于等于2
if %FILE_COUNT% LSS 2 (
    echo 文件数量不足,不执行文件传输
    exit /b
)

for /f "tokens=1-6 delims=/:. " %%a in ("%date% %time%") do (
    set "timestamp=%%b%%c%%d_%%e%%f"
)

:: 创建本地临时目录
mkdir "%TEMP_DIR%" 2>nul

:: 从第一个远程服务器下载文件到本地临时目录
pscp -pw "%SRC_PASSWORD%" -r %SRC_SERVER%:%SRC_PATH%/* %TEMP_DIR%	

:: 将本地临时目录的文件上传到第二个远程服务器
pscp -pw "%DEST_PASSWORD%" -r "%TEMP_DIR%\*" %DEST_SERVER%:%DEST_PATH%

:: 如果上传成功,删除源服务器上的文件
if %ERRORLEVEL%==0 (
    plink -ssh -pw "%SRC_PASSWORD%" -batch %SRC_SERVER% "rm -rf %SRC_PATH%/*"
    echo 已成功删除源服务器上的文件
) else (
    echo 文件传输失败,未删除源服务器上的文件
)

:: 移动临时文件夹到带时间戳的目录
move "%TEMP_DIR%" "%TEMP_DIR%_%timestamp%"

echo 文件传输完成

将远程服务器文件夹同步到本地 Mac

#!/bin/bash
set -e

# 设置远程机器的地址、用户名和密码
remote_host="user@a.b.c"
remote_dir="/remote_dir/"
local_dir="/local_dir/"

# 将远程机器目录下的所有文件复制到本地目录
scp -r "$remote_host:$remote_dir"* "$local_dir"

if [ $? -eq 0 ]; then
    echo "下载 $remote_dir$local_dir ok了!"
    ssh "$remote_host" "rm -rf ${remote_dir}*"

    if [ $? -eq 0 ]; then
        echo "删除 $remote_dir ok了!"
    else
        echo "删除 $remote_dir 失败了!"
        exit 1
    fi
else
    echo "拷贝到本地失败"
    exit 1
fi

注意事项

  • 安全性:在脚本中包含了远程服务器的登录信息,请确保这个脚本的权限设置是安全的,避免未经授权的用户访问。此外,使用scpssh时,使用SSH密钥认证以增强安全性。

  • 文件路径:确保local_dir目录存在且可写,如果目录不存在,scp操作将会失败。如有必要可以在脚本中加入检查和创建目录的逻辑。

  • 删除操作:在删除远程服务器文件之前,务必确保文件已经成功下载至本地。这里可以考虑在删除之前进行额外的校验,例如校验文件的MD5哈希值,以确保文件完整性。


selenium 指定 chrome 和 chromedriver 位置

使用 webdriver.Chrome

  • 通过 chrome_options.binary_location 参数指定 Chrome 浏览器的路径
  • 通过 Service 的 executable_path 参数指定 chromedriver.exe 的位置

以下是一个 Windows 示例代码:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# 设置 Chrome 浏览器的路径
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Path\To\Your\Chrome\Application\chrome.exe'  # 替换为 Chrome 路径

# 指定 chromedriver.exe 的路径
service = Service(executable_path=r'C:\Path\To\Your\chromedriver.exe')  # 替换为 chromedriver 路径

# 启动浏览器
driver = webdriver.Chrome(service=service, options=chrome_options)
driver.get('https://www.baidu.com')

关键点:

  1. chrome_options.binary_location: 设置 Chrome 浏览器可执行文件的路径。
  2. executable_path: 设置 chromedriver.exe 的路径。
  3. Service: 使用 Service 对象指定 chromedriver.exe 的路径。
  4. webdriver.Chrome: 通过 service 参数传入 Service 对象。

在内网 Windows 离线安装 miniconda 和 python

这几天在内网环境配置 python,稍作记录。需要强调的是,我的方案并没有 100% 完成,目前所有操作都是在 conda 默认的 base 环境中进行,没有完成 conda 安装特定 python 版本这个场景,急着干手头的活,先这样了。

安装 Minicoda

和 Anaconda 的关系

Miniconda 和 Anaconda 都是由Anaconda, Inc. 开发和维护的。

Anaconda 是 一个功能全面的Python发行版本,包含了Python解释器、Conda包管理器以及大量预安装的科学计算、数据分析、机器学习等领域的第三方库(如NumPy、Pandas、SciPy、Jupyter等)。

Miniconda 是 Anaconda 的一个精简版本。仅包含 Python解释器、Conda包管理器和基本的包管理工具,没有预装第三方库。Miniconda 使用的是BSD许可,这意味着可以在商业场景中免费使用 Miniconda。有一说一,就算 Anaconda 是开源的,我也会选择用 Miniconda。

下载

下载: https://docs.anaconda.com/miniconda/miniconda-install/

官方命令行使用

image-20240829下午45329326

img

conda info
conda info --env # 列出所有环境
conda env list # 列出所有环境
python --version
pip --version

查看 conda 的路径

where conda

复制 Scripts这个路径,将它添加到PATH中

新增 script 文件夹路径到 PATH

控制面板->系统和安全->系统->高级系统设置->环境变量->系统变量->Path

image-20240830下午40517367

这样就可以任意打开 cmd 或者 powershell 开始使用conda了。这也是为了方便和 vscode 等其他工具配合。

下载 python 库

我以下载appium-python-client为例子:

在外网环境中下载

在一台可以访问互联网的电脑上,使用以下命令来下载 appium-python-client 及其依赖项:

pip download appium-python-client -i https://pypi.tuna.tsinghua.edu.cn/simple

image-20240902下午20248045

将下载好的 .whl.tar.gz 文件通过U盘或其他方式转移到离线环境中。

在离线环境中安装包

在离线环境中使用 pip 安装下载的文件:

pip install --no-index --find-links=/path/to/downloaded/files appium-python-client

/path/to/downloaded/files 替换为文件夹的路径。

检查安装结果

安装完成后,运行以下命令检查是否成功安装:

pip show appium-python-client

如果能看到包的信息,说明安装成功。


在内网 Windows 离线使用 vscode

内网 Windows 安装 vscode

下载:https://code.visualstudio.com/

正常安装就行。主要关注点是把 code 的路径放到 PATH 路径下。

  1. 打开命令提示符CMD或 PowerShell,按 Win + R,输入 cmdpowershell,然后按回车。

  2. 输入 code 命令

    code --version
    
  3. 检查输出

    如果 code 命令未安装或不可用,将看到类似以下的错误信息

    'code' 不是内部或外部命令,也不是可运行的程序或批处理文件。
    

    如果正常安装,可以跳过下面的步骤。

  4. 打开 VSCode

  5. 打开命令面板:按 Ctrl + Shift + P 打开命令面板。

  6. 输入并选择 Shell Command: Install 'code' command in PATH

  7. 重启终端,然后再次输入 code --version 检查是否可用。

  8. 还是不行的话,手动设置PATH:控制面板->系统和安全->系统->高级系统设置->环境变量->系统变量->Path

下载原有扩展

获取现有的 Vscode 扩展列表

code --list-extensions > vscode-extensions-list.txt

安装了很多,我只挑最紧要的,比如:

ms-ceintl.vscode-language-pack-zh-hans
ms-python.debugpy
ms-python.python
vscodevim.vim

下载

  1. 访问 Visual Studio Code Marketplace

  2. 搜索

  3. 在扩展的页面上,点击右下角的 Download Extension 链接下载 .vsix 文件。

  4. 将所有下载的 .vsix 文件保存在一个文件夹中,比如 vscode-extensions 文件夹。

批量安装扩展

在同一目录下创建一个批处理文件,比如 install-vscode-extensions.bat,内容如下:

@echo off
setlocal

REM 设置扩展文件所在的目录
set "EXT_DIR=%HOMEPATH%\vscode-extensions"

REM 循环遍历该目录下的所有 .vsix 文件并安装
for %%f in ("%EXT_DIR%\*.vsix") do (
    echo Installing %%f ...
    code --install-extension "%%f"
)

echo All extensions installed.
endlocal
pause

注意事项

  • 确保 code 命令在 PATH 中,这样批处理脚本才能正确调用 VSCode 的 CLI 工具。
  • 如果 code 命令不可用,可以通过以下步骤将其添加到 PATH:
    1. 打开 VSCode。
    2. Ctrl+Shift+P,输入 Shell Command: Install 'code' command in PATH,然后按回车。
  • 运行脚本时,确保 VSCode 已经关闭,或者可以同时安装扩展而不关闭 VSCode。

如果批量脚本无法安装,也可以如下手动导入install from VSIX

image-20240830上午112503681

我的中文包好像有点问题,不管它了:

image-20240830上午112421934


使用 Linux 服务器同步 Mac 和 Windows 剪切板 2

接着上一篇文章,在Mac上随手把同步图片和文件的功能也做了,Windows暂时不用,就不做了。简单说明一下内容:

核心逻辑: osascript -e 'clipboard info' 2>/dev/null:

  1. 文件内容处理

    osascript -e 'clipboard info'
    «class furl», 39, «class ut16», 22, «class utf8», 10, «class icns», 781190, Unicode text, 20, string, 10, «class 8BPS», 1068148, GIF picture, 48307, «class jp2 », 66756, JPEG picture, 53765, TIFF picture, 4198020, «class PNGf», 202292, «class BMP », 4194442, «class TPIC», 735063
    
  2. 图片内容检测

    osascript -e 'clipboard info'
    *** Error creating a JP2 color space: falling back to sRGB
    «class PNGf», 30911, «class 8BPS», 120626, GIF picture, 9586, «class jp2 », 30845, JPEG picture, 20160, TIFF picture, 1053698, «class BMP », 1052906, «class TPIC», 46827
    
  3. 文本内容检测

    osascript -e 'clipboard info'
    «class utf8», 96, «class ut16», 186, string, 9, Unicode text, 184
    

还有一个注意点是,文件处理的 «class furl»,路径分隔是:`,所以做了一些其他处理:

osascript -e 'the clipboard as «class furl»'
file Macintosh HD:Users:kelu:Downloads:xxx.sh

以下是具体代码:

# ver 2.0
# 远端路径定义
REMOTE_DIR="/tmp/clipboard"
REMOTE_HOST="1.2.3.4"
REMOTE_USER="user"
REMOTE_PASS="password"

LOCAL_DIR="$HOME/Downloads"
TEXT_FILE="clipboard_sync.txt"
IMAGE_FILE="clipboard_content.png"

# 检查远端是否有 /tmp/clipboard 文件夹
REMOTE_EXISTS=$(sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "[ -d $REMOTE_DIR ] && echo 'exists'")

if [ "$REMOTE_EXISTS" == "exists" ]; then
    echo "# 远端文件夹存在" 
    if sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "[ -f $REMOTE_DIR/$TEXT_FILE ]"; then
        echo "# 拷贝文字到剪切板" 
        sshpass -p "$REMOTE_PASS" scp $REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR/$TEXT_FILE" "$LOCAL_DIR/$TEXT_FILE"
        cat "$LOCAL_DIR/$TEXT_FILE" | pbcopy
        cat "$LOCAL_DIR/$TEXT_FILE" | head -n 1
        echo ""
    elif sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "[ -f $REMOTE_DIR/$IMAGE_FILE ]"; then
        echo "# 下载图片到本地剪切板" 
        sshpass -p "$REMOTE_PASS" scp $REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR/$IMAGE_FILE" "$LOCAL_DIR/$IMAGE_FILE"
        osascript -e "set the clipboard to (read (POSIX file \"$LOCAL_DIR/$IMAGE_FILE\") as «class PNGf»)"
    else
        echo "# 获取远端目录中的文件"
        RANDOM_FILE=$(sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "ls -1 $REMOTE_DIR | shuf -n 1")

        if [ -n "$RANDOM_FILE" ]; then
            echo "# 下载文件 $RANDOM_FILE"
            sshpass -p "$REMOTE_PASS" scp $REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR/$RANDOM_FILE" "$LOCAL_DIR/$RANDOM_FILE"

            filePath="$LOCAL_DIR/$RANDOM_FILE"
osascript <<EOF
set filePath to POSIX file "$filePath" as alias
tell application "Finder"
    set the clipboard to (filePath as «class furl»)
end tell
EOF
        fi
    fi

    echo "# 清除远端数据"
    sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "rm -rf $REMOTE_DIR"
else
    sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $REMOTE_DIR"

    CLIPBOARD_TYPE=$(osascript -e 'clipboard info' 2>/dev/null)


    if echo "$CLIPBOARD_TYPE" | grep -q "furl"; then
        # 获取剪贴板中的路径
        FILE_PATH=$(osascript -e 'the clipboard as «class furl»' | tr -d '"')

        # 将 Mac 路径转换为 POSIX 路径
        FILE_PATH_POSIX=$(osascript -e "POSIX path of POSIX file \"$FILE_PATH\"")

        # 将 POSIX 路径中的冒号替换为斜杠
        FILE_PATH_POSIX=$(echo "$FILE_PATH_POSIX" | sed 's/:/\//g' | sed -e 's/^file Macintosh HD//')

        echo "# 检测到文件路径: $FILE_PATH_POSIX"
        sshpass -p "$REMOTE_PASS" scp "$FILE_PATH_POSIX" $REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR/"
        echo "# 推送远端剪切板文件"
        exit 0
    fi

    if echo "$CLIPBOARD_TYPE" | grep -q "TIFF"; then
        echo "# 将剪切板中的图片保存为文件"
        osascript -e 'set imgData to the clipboard as «class PNGf»
                      set imgFile to open for access POSIX file "'$LOCAL_DIR/$IMAGE_FILE'" with write permission
                      write imgData to imgFile
                      close access imgFile' 2>/dev/null
        sshpass -p "$REMOTE_PASS" scp "$LOCAL_DIR/$IMAGE_FILE" $REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR/"
        echo "# 推送远端剪切板图片"
        rm "$LOCAL_DIR/$IMAGE_FILE"
        exit 0
    fi

    if echo "$CLIPBOARD_TYPE" | grep -q "string\|Unicode text"; then
        echo "# 检测到文本内容"
        pbpaste > "$LOCAL_DIR/$TEXT_FILE"
        sshpass -p "$REMOTE_PASS" scp "$LOCAL_DIR/$TEXT_FILE" $REMOTE_USER@$REMOTE_HOST:"$REMOTE_DIR/$TEXT_FILE"
        echo "# 推送远端剪切板文字"
        cat "$LOCAL_DIR/$TEXT_FILE" | head -n 1
        rm "$LOCAL_DIR/$TEXT_FILE"
        exit 0
    fi

    sshpass -p "$REMOTE_PASS" ssh $REMOTE_USER@$REMOTE_HOST "rm -rf $REMOTE_DIR"
fi