#include "ProcessUtility.h" #include "BoostLog.h" #include "boost/algorithm/string.hpp" #include #include #ifdef __linux__ #include #elif defined(_WIN32) #include #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 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}); } }