plink 、pscp非交互式自动执行相关命令
pscp 和 plink 工具可以用于在Windows上以非交互式的方式进行自动化操作:
pscp:用于自动化的传输文件。plink:用于在Windows上远程自动执行Linux命令。
一、plink 远程执行Linux命令
1、batch 文件中执行Linux 命令
在一些场景下有些 Linux命令操作需要将其放在batch文件中,提供给用户进行一键式自动运行。在batch文件中内容如下:
batch 内容
@echo off
setlocal
set remoteHost=172.16.21.100
set username=Tom
set password=xod123
set linuxCommand="cd /home/Tom/x666 && ls"
set plinkPath="D:/Programs/plink.exe"
%plinkPath% -batch -ssh -l %username% -pw %password% %remoteHost% %linuxCommand%
【注意】:batch脚本中 set命令语法很严格, 变量的等号前后都不能有空格,否则会导致意外的错误,如:
set cmd = "ls" 后面的 %cmd%会无法取值,因为变量后的空格也会被识别为变量的一部分,即%cmd %导致变量无法展开,最终导致脚本无法有效执行。
以上参数说明:
- 通过 set 设置相关变量的值,以便后续直接使用
plink.exe程序直接通过 ssh 来进行远程执行Linux上的命令行:-batch:可以用来取消出现交互信息,如Access granted. Press Return to begin session.。直接显示远程命令执行的结果。-ssh:使用ssh协议-l:login 表示远程Linux设备的用户名,后接用户名-pw:表示密码信息,后面接用户密码。- 最后就是IP地址和需要执行的Linux命令
2、代码中 QProcess 直接远程执行Linux命令行,无batch文件
在Qt 中常见的方式是使用 QProcess 来启动这个进程,去执行远程的命令行,这个方式不通过启动 Batch文件,能够有效的避免了中文路径、空格导致的问题
Code
// 调用代码
QString plinkPath = "D:/Programs/plink.exe";
QString userName = "Tom";
QString passWd = "xod123";
QString host = "172.16.21.100";
QString cmdRemote = "cd /home/Tom/x666 && ls";
QString cmd = QString("\"%1\" -ssh -l %2 -pw %3 %4 \"%5\"").arg(plinkPath, userName, passWd, host, cmdRemote);
QString outputMsg;
bool ret = StartProcess(cmd, outputMsg, "UTF-8");
// 执行函数,参数cmd为命令行,QProcess 并不能解释脚本内容,它会把第一个参数(第一个空格前内容)当作启动程序
bool StartProcess(const QString& cmd, QString& outputMsg, std::string encode = "UTF-8")
{
QProcess process;
process.setProcessChannelMode(QProcess::SeparateChannels);
process.start(cmd);
// 需要判断进程是否成功启动
if(!process.waitForStarted())
{
outputMsg = process.errorString();
return false;
}
if (!process.waitForFinished(30000))
{
outputMsg = "Process timeout.";
return false;
}
const QTextCodec* codec = QTextCodec::codecForName(encode.c_str());
const QString outMsg = codec->toUnicode(process.readAllStandardOutput());
const QString errMsg = codec->toUnicode(process.readAllStandardError());
if (errMsg.trimmed().isEmpty())
{
outputMsg = outMsg;
return true;
}
outputMsg = errMsg;
return false;
}
【注意】:
在Linux上执行的命令行,一般是 UTF-8编码,而Windows上一般是gbk编码,所以如果是远程执行Linux上的命令行中有中文字符,需要将其转换成 UTF-8的编码格式才能正常显示,如果执行的 cmd 直接是Windows设备上的命令,则需要设置gbk的编码形式
二、pscp传输文件: pscp.exe [options] [source] [user]@[host]:[destination]
经常用于无需输入密码的自动化执行流程中,执行指令如下:
pscp -i [C:\private_key.ppk] [file1.txt] user@remote_host:/home/user/:使用密匙自动化传输文件。pscp -pw [123456] [file1.txt file2.txt] user@remote_host:/home/user/:使用明文密码的形式进行传输文件,多个文件时,并列在一起
1、以batch脚本的形式进行执行传输
batch
@echo off
setlocal
set pscpPath="D:/pscp.exe"
set password=x012345
set srcFiles="D:/Tmp/file1.txt" "D:/Tmp/Test Files/config.ini" "D:/Tmp/tmp.png"
set userName=ad
set host=172.16.20.196
set destPath="/home/hut/x01"
%pscpPath% -pw %password% %srcFiles% %userName%@%host%:%destPath%
endlocal
以上的内容存放在batch文件中,可以提供给用户来直接运行batch文件。
三、QProcess 启动batch脚本
通过QProcess直接运行batch脚本需要注意路径中的特殊字符等问题,以下为完整的实现接口:
#include <QProcess>
#include <QDir>
#include <QTextCodec>
#include <QFileInfo>
#include <QDebug>
/**
* @brief 执行指定的 Batch 脚本(支持中文路径和空格路径)
* @param batchPath Batch文件的完整路径
* @param outputInfo [输出] 执行过程中的标准输出和错误输出
* @return bool 执行成功返回 true,失败返回 false
*/
bool ExecuteBatch(const QString& batchPath, QString & outputInfo)
{
outputInfo.clear();
// 1. 基础检查:判断文件是否存在
if (!QFileInfo::exists(batchPath)) {
outputInfo = QString("Error: File not found: %1").arg(batchPath);
return false;
}
// 2. 路径转换:将路径转换为 Windows 原生格式 (将 / 替换为 \ )
// 虽然 Qt 支持 /,但在调用 cmd.exe 时,原生反斜杠最稳健
QString nativePath = QDir::toNativeSeparators(batchPath);
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels); // 将标准输出和标准错误合并,方便查看所有日志
// 3. 核心修正:使用 cmd.exe /c 来运行
// QProcess 的参数列表机制会自动处理路径中的空格,自动添加引号,无需手动拼接 "\""
QString program = "cmd.exe";
QStringList arguments;
arguments << "/c" << nativePath;
// 4. 启动进程
process.start(program, arguments);
// 5. 等待启动
if (!process.waitForStarted()) {
outputInfo = QString("Error: Failed to start cmd.exe. %1").arg(process.errorString());
return false;
}
// 6. 等待结束 (这里设置超时时间为 30000ms,即30秒,可视情况调整,-1表示无限等待)
// 如果脚本执行时间较长,建议增加此值或设为 -1
if (!process.waitForFinished(30000)) {
outputInfo = "Error: Process operation timed out.";
process.kill(); // 超时则杀死进程
return false;
}
// 7. 获取输出内容并处理编码
// cmd.exe 在中文 Windows 下默认输出是 GBK 编码
// 如果不转换,获取到的中文(如“系统找不到指定路径”)会是乱码
QByteArray rawOutput = process.readAll();
// 尝试使用系统本地编码解码 (通常是 GBK)
// 如果你的 batch 脚本内部显式调用了 chcp 65001,则这里可能需要改用 UTF-8
QTextCodec *codec = QTextCodec::codecForLocale();
if (codec) {
outputInfo = codec->toUnicode(rawOutput);
} else {
outputInfo = QString::fromLocal8Bit(rawOutput);
}
// 8. 判断执行结果
// exitCode == 0 通常表示执行成功
if (process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0) {
return true;
} else {
outputInfo += QString(" Process failed with exit code: %1").arg(process.exitCode());
return false;
}
}
浙公网安备 33010602011771号