201 lines
6.5 KiB
C++
201 lines
6.5 KiB
C++
|
#include "ProcessUtility.h"
|
||
|
#include "BoostLog.h"
|
||
|
#include "boost/algorithm/string.hpp"
|
||
|
#include <regex>
|
||
|
#include <sstream>
|
||
|
#ifdef __linux__
|
||
|
#include <unistd.h>
|
||
|
#elif defined(_WIN32)
|
||
|
#include <boost/winapi/dll.hpp>
|
||
|
#endif
|
||
|
|
||
|
bool DockerUtility::supervisorStatus(std::string_view container, const std::string &module) {
|
||
|
using namespace boost::process;
|
||
|
boost::process::ipstream ips;
|
||
|
auto docker = search_path("docker");
|
||
|
auto ctl = boost::process::search_path("supervisorctl");
|
||
|
auto env = boost::this_process::environment();
|
||
|
if (env.count("USER")) {
|
||
|
auto user = env["USER"].to_string();
|
||
|
system(docker, args = {"exec", "-u", user, container.data(), "supervisorctl", "status", module}, std_out > ips);
|
||
|
std::string line;
|
||
|
if (!ips) return false;
|
||
|
std::getline(ips, line);
|
||
|
if (line.empty()) return false;
|
||
|
boost::algorithm::trim(line);
|
||
|
std::vector<std::string> s;
|
||
|
boost::algorithm::split(s, line, boost::algorithm::is_any_of(" "), boost::algorithm::token_compress_on);
|
||
|
if (s.size() < 3) return false;
|
||
|
return s.at(2) == "RUNNING";
|
||
|
} else {
|
||
|
LOG(error) << "this_process did not contain USER env value.";
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool DockerUtility::running(std::string_view container, std::error_code &error) {
|
||
|
#ifdef __linux__
|
||
|
using namespace boost::process;
|
||
|
boost::process::ipstream stream;
|
||
|
std::ostringstream oss;
|
||
|
oss << "docker ps -q --filter \"name=" << container << "\" --filter \"status=running\"";
|
||
|
system(oss.str(), boost::process::std_out > stream, error);
|
||
|
if (error) return false;
|
||
|
bool ret = false;
|
||
|
std::string line;
|
||
|
while (std::getline(stream, line) && !line.empty()) {
|
||
|
ret = true;
|
||
|
break;
|
||
|
}
|
||
|
return ret;
|
||
|
#else
|
||
|
return false;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
std::string NativeUtility::currentExecutable() {
|
||
|
// win32 GetModuleFileNameA
|
||
|
#ifdef __linux__
|
||
|
char buffer[512] = {0};
|
||
|
auto status = readlink("/proc/self/exe", buffer, sizeof(buffer));
|
||
|
return status == -1 ? std::string() : std::string(buffer);
|
||
|
#else
|
||
|
char buffer[MAX_PATH];
|
||
|
boost::winapi::get_module_file_name(nullptr, buffer, MAX_PATH);
|
||
|
return buffer;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
std::string NativeUtility::executableDirectory() {
|
||
|
auto path = currentExecutable();
|
||
|
#ifdef __linux__
|
||
|
auto slashPos = path.find_last_of("/");
|
||
|
#else
|
||
|
auto slashPos = path.find_last_of("\\");
|
||
|
#endif
|
||
|
return path.substr(0, slashPos);
|
||
|
}
|
||
|
|
||
|
std::string NativeUtility::applicationDataDirectory(bool create) {
|
||
|
std::string directory;
|
||
|
|
||
|
#ifdef WIN32
|
||
|
DWORD bufferSize = GetEnvironmentVariable("APPDATA", 0, 0);
|
||
|
char *buffer = new char[bufferSize + 2];
|
||
|
GetEnvironmentVariable("APPDATA", buffer, bufferSize);
|
||
|
directory.assign(buffer);
|
||
|
delete[] buffer;
|
||
|
#else
|
||
|
const char *result = std::getenv("XDG_CONFIG_HOME");
|
||
|
if (result && strlen(result)) {
|
||
|
directory = std::string(result);
|
||
|
} else {
|
||
|
directory = std::string(std::getenv("HOME")) + std::string("/.config/");
|
||
|
}
|
||
|
#endif
|
||
|
auto exePath = currentExecutable();
|
||
|
auto slashPos = exePath.find_last_of("\\");
|
||
|
auto dotPos = exePath.find_last_of(".");
|
||
|
auto appName = exePath.substr(slashPos + 1, dotPos - slashPos - 1);
|
||
|
std::ostringstream oss;
|
||
|
oss << directory << "/" << appName << "/";
|
||
|
directory = oss.str();
|
||
|
if (create) {
|
||
|
try {
|
||
|
std::filesystem::path path(std::filesystem::u8path(directory));
|
||
|
if (!std::filesystem::exists(path)) {
|
||
|
std::filesystem::create_directories(path);
|
||
|
}
|
||
|
} catch (...) {
|
||
|
}
|
||
|
}
|
||
|
return directory;
|
||
|
}
|
||
|
|
||
|
std::string NativeUtility::homeDirectory() {
|
||
|
std::string directory;
|
||
|
#ifdef WIN32
|
||
|
DWORD bufferSize = GetEnvironmentVariable("USERPROFILE", 0, 0);
|
||
|
char *buffer = new char[bufferSize + 2];
|
||
|
GetEnvironmentVariable("USERPROFILE", buffer, bufferSize);
|
||
|
directory.assign(buffer);
|
||
|
delete[] buffer;
|
||
|
#else
|
||
|
directory = std::string(std::getenv("HOME"));
|
||
|
#endif
|
||
|
return directory;
|
||
|
}
|
||
|
|
||
|
bool NativeUtility::processRunning(const std::string &nameFilter) {
|
||
|
boost::process::ipstream ips;
|
||
|
// for unknow reason,on gdb debug mode,the columns is very short.
|
||
|
boost::process::system("ps -eF --columns 999", boost::process::std_out > ips);
|
||
|
std::string line;
|
||
|
std::regex regex(nameFilter);
|
||
|
while (std::getline(ips, line)) {
|
||
|
if (line.empty()) continue;
|
||
|
// LOG(debug) << "processRunning: " << line;
|
||
|
if (std::regex_search(line, regex)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void DockerUtility::executeBashCommand(const std::string &command) {
|
||
|
std::ostringstream oss;
|
||
|
oss << "bash -c \"" << command << "\"";
|
||
|
boost::process::system("bash -c \" \"");
|
||
|
|
||
|
// ps -aux | grep rosbridge | awk '{print $2}' | xargs kill -s 9 2>/dev/null
|
||
|
}
|
||
|
|
||
|
void DockerUtility::execute(const std::string_view &container, const std::string_view &command) {
|
||
|
std::ostringstream oss;
|
||
|
auto env = boost::this_process::environment();
|
||
|
auto user = env["USER"].to_string();
|
||
|
oss << "docker exec -u " << user << " -d " << container << " " << command;
|
||
|
using namespace boost::process;
|
||
|
system(oss.str());
|
||
|
}
|
||
|
|
||
|
void DockerUtility::kill(const std::string &nameFilter) {
|
||
|
std::ostringstream oss;
|
||
|
oss << "ps -aux | grep " << nameFilter << " | awk '{print $2}' | xargs kill -s 9 2>/dev/null";
|
||
|
executeBashCommand(oss.str());
|
||
|
}
|
||
|
|
||
|
bool DockerUtility::containerExisted(const std::string_view &name) {
|
||
|
boost::process::ipstream ips;
|
||
|
std::ostringstream oss;
|
||
|
oss << "docker ps -aq --filter name=" << name;
|
||
|
boost::process::system(oss.str(), boost::process::std_out > ips);
|
||
|
std::string line;
|
||
|
while (std::getline(ips, line)) {
|
||
|
if (line.empty()) continue;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void DockerUtility::supervisorctl(const std::string_view &container, const std::string &module, bool isStart) {
|
||
|
using namespace boost::process;
|
||
|
auto docker = search_path("docker");
|
||
|
auto env = boost::this_process::environment();
|
||
|
auto user = env["USER"].to_string();
|
||
|
system(docker, args = {"exec", "-u", user, container.data(), "supervisorctl", isStart ? "start" : "stop", module});
|
||
|
}
|
||
|
|
||
|
void DockerUtility::stop(const std::string &nameFilter) {
|
||
|
using namespace boost::process;
|
||
|
ipstream ips;
|
||
|
std::ostringstream oss;
|
||
|
oss << "docker ps -q --filter \"name=" << nameFilter << "\" --filter \"status=running\" ";
|
||
|
system(oss.str(), std_out > ips);
|
||
|
std::string id;
|
||
|
auto docker = search_path("docker");
|
||
|
while (std::getline(ips, id) && !id.empty()) {
|
||
|
system(docker, "stop", args += {id});
|
||
|
}
|
||
|
}
|