This commit is contained in:
@ -53,14 +53,14 @@ bool service_runner::install(bool silent) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Create service directory
|
// Create service directory
|
||||||
if (0!=runner::execute_cmd("mkdir -p " + remotepath::service(mServer, mService),{},"",{},true,false,mServerEnv.get_SSH_INFO()))
|
if (0!=runner::execute_cmd("mkdir",{"-p",remotepath::service(mServer, mService)},"",{},true,false,mServerEnv.get_SSH_INFO()))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to create service directory " << remotepath::service(mServer, mService) << std::endl;
|
std::cerr << "Failed to create service directory " << remotepath::service(mServer, mService) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if rsync is installed on remote host
|
// Check if rsync is installed on remote host
|
||||||
if (0!=runner::execute_cmd("which rsync",{},"",{},true,false,mServerEnv.get_SSH_INFO()))
|
if (0!=runner::execute_cmd("which",{"rsync"},"",{},true,false,mServerEnv.get_SSH_INFO()))
|
||||||
{
|
{
|
||||||
std::cerr << "rsync is not installed on the remote host" << std::endl;
|
std::cerr << "rsync is not installed on the remote host" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -748,14 +748,12 @@ std::string service_runner::get_latest_backup_file(const std::string& server, co
|
|||||||
bool service_runner::rsync_copy(const std::string& local_path, const std::string& remote_path, bool silent) {
|
bool service_runner::rsync_copy(const std::string& local_path, const std::string& remote_path, bool silent) {
|
||||||
std::cout << "Copying: [LOCAL] " << local_path << std::endl << std::string(8,' ')<<"[REMOTE] " << remote_path << std::endl;
|
std::cout << "Copying: [LOCAL] " << local_path << std::endl << std::string(8,' ')<<"[REMOTE] " << remote_path << std::endl;
|
||||||
|
|
||||||
std::string rsync_cmd = "rsync --delete -zrpc -e 'ssh -p " + mServerEnv.get_SSH_PORT() + "' " +
|
if (0 != runner::execute_cmd(
|
||||||
quote(local_path) + " " +
|
"rsync",
|
||||||
mServerEnv.get_SSH_USER() + "@" + mServerEnv.get_SSH_HOST() + ":" +
|
{"--delete","--mkpath","-zrpc","-e",quote("ssh -p " + mServerEnv.get_SSH_PORT()),local_path,
|
||||||
quote(remote_path);
|
mServerEnv.get_SSH_USER()+"@"+mServerEnv.get_SSH_HOST()+":"+remote_path},
|
||||||
|
"", {}, true, false)) {
|
||||||
if (0 != runner::execute_cmd(rsync_cmd, {}, "", {}, true, false, mServerEnv.get_SSH_INFO())) {
|
|
||||||
std::cerr << "Failed to copy files using rsync" << std::endl;
|
std::cerr << "Failed to copy files using rsync" << std::endl;
|
||||||
std::cerr << "Is rsync installed on the remote host?" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -88,34 +88,34 @@ std::string ssh_build_remote_command(const std::string& command, const std::vect
|
|||||||
}
|
}
|
||||||
remote_cmd << command;
|
remote_cmd << command;
|
||||||
for (const auto& arg : args) {
|
for (const auto& arg : args) {
|
||||||
remote_cmd << " '" << arg << "'";
|
remote_cmd << " " << arg;
|
||||||
}
|
}
|
||||||
return remote_cmd.str();
|
return remote_cmd.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility function to escape special shell characters
|
// // Utility function to escape special shell characters
|
||||||
std::string escape_shell_arg(const std::string& arg) {
|
// std::string escape_shell_arg(const std::string& arg) {
|
||||||
std::ostringstream escaped;
|
// std::ostringstream escaped;
|
||||||
escaped << '"';
|
// escaped << '"';
|
||||||
for (char c : arg) {
|
// for (char c : arg) {
|
||||||
if (c == '"' || c == '\\' || c == '$' || c == '`') {
|
// if (c == '"' || c == '\\' || c == '$' || c == '`') {
|
||||||
escaped << '\\';
|
// escaped << '\\';
|
||||||
}
|
// }
|
||||||
escaped << c;
|
// escaped << c;
|
||||||
}
|
// }
|
||||||
escaped << '"';
|
// escaped << '"';
|
||||||
return escaped.str();
|
// return escaped.str();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// For non-interactive SSH, just build the command with args
|
// // For non-interactive SSH, just build the command with args
|
||||||
std::string ssh_build_command_only(const std::string& command, const std::vector<std::string>& args) {
|
// std::string ssh_build_command_only(const std::string& command, const std::vector<std::string>& args) {
|
||||||
std::ostringstream remote_cmd;
|
// std::ostringstream remote_cmd;
|
||||||
remote_cmd << command;
|
// remote_cmd << command;
|
||||||
for (const auto& arg : args) {
|
// for (const auto& arg : args) {
|
||||||
remote_cmd << " " << escape_shell_arg(arg);
|
// remote_cmd << " " << arg;
|
||||||
}
|
// }
|
||||||
return remote_cmd.str();
|
// return remote_cmd.str();
|
||||||
}
|
// }
|
||||||
|
|
||||||
int ssh_interactive_shell_session(ssh_session session, ssh_channel channel, const std::string& remote_cmd_str, const std::string& command, std::string* output) {
|
int ssh_interactive_shell_session(ssh_session session, ssh_channel channel, const std::string& remote_cmd_str, const std::string& command, std::string* output) {
|
||||||
// Request a PTY with xterm-256color type for color support
|
// Request a PTY with xterm-256color type for color support
|
||||||
@ -208,7 +208,7 @@ int ssh_exec_command(ssh_session session, ssh_channel channel, const std::string
|
|||||||
cmd_with_env << "env ";
|
cmd_with_env << "env ";
|
||||||
for (const auto& kv : env) {
|
for (const auto& kv : env) {
|
||||||
if (kv.first == "SSHPASS") continue;
|
if (kv.first == "SSHPASS") continue;
|
||||||
cmd_with_env << kv.first << "='" << kv.second << "' ";
|
cmd_with_env << kv.first << "=\"" << kv.second << "\" ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,21 +219,15 @@ int ssh_exec_command(ssh_session session, ssh_channel channel, const std::string
|
|||||||
if (!working_dir.empty()) {
|
if (!working_dir.empty()) {
|
||||||
cmd_with_env << "cd " << working_dir << " && ";
|
cmd_with_env << "cd " << working_dir << " && ";
|
||||||
}
|
}
|
||||||
|
cmd_with_env << remote_cmd_str;
|
||||||
// Add the command, but replace any single quotes with '\''
|
|
||||||
std::string escaped_cmd = remote_cmd_str;
|
|
||||||
size_t pos = 0;
|
|
||||||
while ((pos = escaped_cmd.find('\'', pos)) != std::string::npos) {
|
|
||||||
escaped_cmd.replace(pos, 1, "'\\''");
|
|
||||||
pos += 4; // Length of "'\\''"
|
|
||||||
}
|
|
||||||
cmd_with_env << escaped_cmd;
|
|
||||||
|
|
||||||
// Close the single quote
|
// Close the single quote
|
||||||
cmd_with_env << "'";
|
cmd_with_env << "'";
|
||||||
|
|
||||||
std::string final_cmd = cmd_with_env.str();
|
std::string final_cmd = cmd_with_env.str();
|
||||||
|
|
||||||
|
std::cout << "Final remote command: " << final_cmd << std::endl;
|
||||||
|
|
||||||
int rc = ssh_channel_request_exec(channel, final_cmd.c_str());
|
int rc = ssh_channel_request_exec(channel, final_cmd.c_str());
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
std::string error = std::string("Failed to exec remote command: ") + ssh_get_error(session);
|
std::string error = std::string("Failed to exec remote command: ") + ssh_get_error(session);
|
||||||
@ -297,27 +291,34 @@ int local_execute_cmd(
|
|||||||
bool interactive,
|
bool interactive,
|
||||||
std::string* output
|
std::string* output
|
||||||
) {
|
) {
|
||||||
|
std::cerr << "Local command: " << command << std::endl;
|
||||||
|
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
bool use_pipe = output && !interactive;
|
bool use_pipe = output && !interactive;
|
||||||
if (use_pipe && pipe(pipefd) == -1) {
|
if (use_pipe && pipe(pipefd) == -1) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
|
std::cerr << "Pipe error: " << strerror(errno) << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
perror("fork");
|
perror("fork");
|
||||||
|
std::cerr << "Fork error: " << strerror(errno) << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
if (!working_dir.empty()) {
|
if (!working_dir.empty()) {
|
||||||
if (chdir(working_dir.c_str()) != 0) {
|
if (chdir(working_dir.c_str()) != 0) {
|
||||||
perror("chdir");
|
perror("chdir");
|
||||||
|
std::cerr << "Chdir error: " << strerror(errno) << std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& kv : env) {
|
for (const auto& kv : env) {
|
||||||
setenv(kv.first.c_str(), kv.second.c_str(), 1);
|
setenv(kv.first.c_str(), kv.second.c_str(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_pipe) {
|
if (use_pipe) {
|
||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
dup2(pipefd[1], STDOUT_FILENO);
|
dup2(pipefd[1], STDOUT_FILENO);
|
||||||
@ -338,6 +339,12 @@ int local_execute_cmd(
|
|||||||
argv.push_back(const_cast<char*>(arg.c_str()));
|
argv.push_back(const_cast<char*>(arg.c_str()));
|
||||||
}
|
}
|
||||||
argv.push_back(nullptr);
|
argv.push_back(nullptr);
|
||||||
|
|
||||||
|
std::cerr << "Local command: " << command << std::endl;
|
||||||
|
for (const auto& arg : args) {
|
||||||
|
std::cerr << "Local arg: " << arg << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
execvp(command.c_str(), argv.data());
|
execvp(command.c_str(), argv.data());
|
||||||
perror("execvp");
|
perror("execvp");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -355,6 +362,7 @@ int local_execute_cmd(
|
|||||||
}
|
}
|
||||||
int status = 0;
|
int status = 0;
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
|
std::cerr << "Waitpid status: " << status << std::endl;
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
} else {
|
} else {
|
||||||
@ -380,6 +388,7 @@ int execute_cmd(
|
|||||||
ssh_session session = ssh_connect_and_auth(&sshinfo, env, &error);
|
ssh_session session = ssh_connect_and_auth(&sshinfo, env, &error);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
if (output) *output = error;
|
if (output) *output = error;
|
||||||
|
std::cerr << "SSH connection error: " << error << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ssh_channel channel = ssh_channel_new(session);
|
ssh_channel channel = ssh_channel_new(session);
|
||||||
@ -387,6 +396,7 @@ int execute_cmd(
|
|||||||
if (output) *output = "Failed to create SSH channel.";
|
if (output) *output = "Failed to create SSH channel.";
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
std::cerr << "SSH channel error: " << output->c_str() << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int rc = ssh_channel_open_session(channel);
|
int rc = ssh_channel_open_session(channel);
|
||||||
@ -395,16 +405,16 @@ int execute_cmd(
|
|||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
std::cerr << "SSH channel open error: " << output->c_str() << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
std::string remote_cmd_str = ssh_build_remote_command(command, args, working_dir, {});
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
std::string remote_cmd_str = ssh_build_remote_command(command, args, working_dir, {});
|
|
||||||
ret = ssh_interactive_shell_session(session, channel, remote_cmd_str, command, output);
|
ret = ssh_interactive_shell_session(session, channel, remote_cmd_str, command, output);
|
||||||
} else {
|
} else {
|
||||||
// For non-interactive, handle working directory in ssh_exec_command
|
// For non-interactive, handle working directory in ssh_exec_command
|
||||||
std::string remote_cmd_str = ssh_build_command_only(command, args);
|
|
||||||
ret = ssh_exec_command(session, channel, remote_cmd_str, silent, output, env, working_dir);
|
ret = ssh_exec_command(session, channel, remote_cmd_str, silent, output, env, working_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,11 +423,16 @@ int execute_cmd(
|
|||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
|
||||||
if (output) trim(output);
|
if (output) trim(output);
|
||||||
|
|
||||||
|
std::cerr << "SSH command execution result: " << ret << std::endl;
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
int ret=local_execute_cmd(command, args, working_dir, env, silent, interactive, output);
|
int ret=local_execute_cmd(command, args, working_dir, env, silent, interactive, output);
|
||||||
if (output) trim(output);
|
if (output) trim(output);
|
||||||
|
|
||||||
|
std::cerr << "Local command execution result: " << ret << std::endl;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user