mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
[Process] Process Execution Refactor (#2632)
* Swap execute output method * Create "Process" class and move random string to Strings * test * Tweaks
This commit is contained in:
parent
70719852d6
commit
f5126222c2
@ -64,6 +64,7 @@ SET(common_sources
|
||||
path_manager.cpp
|
||||
perl_eqdb.cpp
|
||||
perl_eqdb_res.cpp
|
||||
process/process.cpp
|
||||
proc_launcher.cpp
|
||||
profanity_manager.cpp
|
||||
ptimer.cpp
|
||||
@ -568,6 +569,7 @@ SET(common_headers
|
||||
packet_functions.h
|
||||
path_manager.cpp
|
||||
platform.h
|
||||
process/process.h
|
||||
proc_launcher.h
|
||||
profanity_manager.h
|
||||
profiler.h
|
||||
|
||||
@ -1,48 +1,15 @@
|
||||
#include "global_define.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "crash.h"
|
||||
#include "strings.h"
|
||||
#include "process/process.h"
|
||||
|
||||
inline std::string random_string(size_t length)
|
||||
{
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
const size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[static_cast<size_t>(std::rand()) % max_index];
|
||||
};
|
||||
std::string str(length, 0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
#include <cstdio>
|
||||
|
||||
std::string execute(const std::string &cmd, bool return_result = true)
|
||||
{
|
||||
std::string random = "/tmp/" + random_string(25);
|
||||
const char *file_name = random.c_str();
|
||||
|
||||
if (return_result) {
|
||||
#ifdef _WINDOWS
|
||||
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||
#else
|
||||
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||
#if WINDOWS
|
||||
#define popen _popen
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std::system((cmd).c_str());
|
||||
}
|
||||
|
||||
std::string result;
|
||||
|
||||
if (return_result) {
|
||||
std::ifstream file(file_name);
|
||||
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
|
||||
std::remove(file_name);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(_WINDOWS) && defined(CRASH_LOGGING)
|
||||
#include "StackWalker.h"
|
||||
@ -167,7 +134,7 @@ void set_exception_handler() {
|
||||
|
||||
void print_trace()
|
||||
{
|
||||
bool does_gdb_exist = execute("gdb -v").find("GNU") != std::string::npos;
|
||||
bool does_gdb_exist = Strings::Contains(Process::execute("gdb -v"), "GNU");
|
||||
if (!does_gdb_exist) {
|
||||
LogCrash(
|
||||
"[Error] GDB is not installed, if you want crash dumps on Linux to work properly you will need GDB installed"
|
||||
@ -176,12 +143,12 @@ void print_trace()
|
||||
}
|
||||
|
||||
auto uid = geteuid();
|
||||
std::string temp_output_file = "/tmp/dump-output";
|
||||
std::string temp_output_file = fmt::format("/tmp/dump-output-{}", Strings::Random(10));
|
||||
|
||||
// check for passwordless sudo if not root
|
||||
if (uid != 0) {
|
||||
bool has_passwordless_sudo = execute("sudo -n true").find("a password is required") == std::string::npos;
|
||||
if (!has_passwordless_sudo) {
|
||||
bool sudo_password_required = Strings::Contains(Process::execute("sudo -n true"), "a password is required");
|
||||
if (sudo_password_required) {
|
||||
LogCrash(
|
||||
"[Error] Current user does not have passwordless sudo installed. It is required to automatically process crash dumps with GDB as non-root."
|
||||
);
|
||||
@ -210,7 +177,7 @@ void print_trace()
|
||||
abort(); /* If gdb failed to start */
|
||||
}
|
||||
else {
|
||||
waitpid(child_pid, NULL, 0);
|
||||
waitpid(child_pid, nullptr, 0);
|
||||
}
|
||||
|
||||
std::ifstream input(temp_output_file);
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#include "../eqemu_config.h"
|
||||
#include "../database_schema.h"
|
||||
#include "../file.h"
|
||||
#include "../process/process.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@ -40,38 +41,6 @@
|
||||
|
||||
#define DATABASE_DUMP_PATH "backups/"
|
||||
|
||||
/**
|
||||
* @param cmd
|
||||
* @param return_result
|
||||
* @return
|
||||
*/
|
||||
std::string DatabaseDumpService::execute(const std::string &cmd, bool return_result = true)
|
||||
{
|
||||
const char *file_name = "db-exec-result.txt";
|
||||
|
||||
if (return_result) {
|
||||
#ifdef _WINDOWS
|
||||
std::system((cmd + " > " + file_name + " 2>&1").c_str());
|
||||
#else
|
||||
std::system((cmd + " > " + file_name).c_str());
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std::system((cmd).c_str());
|
||||
}
|
||||
|
||||
std::string result;
|
||||
|
||||
if (return_result) {
|
||||
std::ifstream file(file_name);
|
||||
result = {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
|
||||
std::remove(file_name);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@ -88,7 +57,7 @@ bool DatabaseDumpService::IsMySQLInstalled()
|
||||
*/
|
||||
bool DatabaseDumpService::IsTarAvailable()
|
||||
{
|
||||
std::string version_output = execute("tar --version");
|
||||
std::string version_output = Process::execute("tar --version");
|
||||
|
||||
return version_output.find("GNU tar") != std::string::npos;
|
||||
}
|
||||
@ -99,7 +68,7 @@ bool DatabaseDumpService::IsTarAvailable()
|
||||
*/
|
||||
bool DatabaseDumpService::Is7ZipAvailable()
|
||||
{
|
||||
std::string version_output = execute("7z --help");
|
||||
std::string version_output = Process::execute("7z --help");
|
||||
|
||||
return version_output.find("7-Zip") != std::string::npos;
|
||||
}
|
||||
@ -117,7 +86,7 @@ bool DatabaseDumpService::HasCompressionBinary()
|
||||
*/
|
||||
std::string DatabaseDumpService::GetMySQLVersion()
|
||||
{
|
||||
std::string version_output = execute("mysql --version");
|
||||
std::string version_output = Process::execute("mysql --version");
|
||||
|
||||
return Strings::Trim(version_output);
|
||||
}
|
||||
@ -399,8 +368,8 @@ void DatabaseDumpService::Dump()
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string execution_result = execute(execute_command, IsDumpOutputToConsole());
|
||||
if (!execution_result.empty()) {
|
||||
std::string execution_result = Process::execute(execute_command);
|
||||
if (!execution_result.empty() && IsDumpOutputToConsole()) {
|
||||
std::cout << execution_result;
|
||||
}
|
||||
}
|
||||
@ -416,7 +385,7 @@ void DatabaseDumpService::Dump()
|
||||
LogInfo("Compression requested... Compressing dump [{}.sql]", GetDumpFileNameWithPath());
|
||||
|
||||
if (IsTarAvailable()) {
|
||||
execute(
|
||||
Process::execute(
|
||||
fmt::format(
|
||||
"tar -zcvf {}.tar.gz -C {} {}.sql",
|
||||
GetDumpFileNameWithPath(),
|
||||
@ -427,7 +396,7 @@ void DatabaseDumpService::Dump()
|
||||
LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath());
|
||||
}
|
||||
else if (Is7ZipAvailable()) {
|
||||
execute(
|
||||
Process::execute(
|
||||
fmt::format(
|
||||
"7z a -t7z {}.zip {}.sql",
|
||||
GetDumpFileNameWithPath(),
|
||||
|
||||
@ -73,7 +73,6 @@ private:
|
||||
std::string dump_path;
|
||||
std::string dump_file_name;
|
||||
|
||||
std::string execute(const std::string &cmd, bool return_result);
|
||||
bool IsMySQLInstalled();
|
||||
std::string GetMySQLVersion();
|
||||
std::string GetBaseMySQLDumpCommand();
|
||||
|
||||
18
common/process/process.cpp
Normal file
18
common/process/process.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "process.h"
|
||||
|
||||
std::string Process::execute(const std::string &cmd)
|
||||
{
|
||||
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
if (!pipe) { return "ERROR"; }
|
||||
char buffer[128];
|
||||
std::string result;
|
||||
while (!feof(pipe.get())) {
|
||||
if (fgets(buffer, 128, pipe.get()) != nullptr) {
|
||||
result += buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
19
common/process/process.h
Normal file
19
common/process/process.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef EQEMU_PROCESS_H
|
||||
#define EQEMU_PROCESS_H
|
||||
|
||||
#include "../strings.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#if _WIN32
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
#endif
|
||||
|
||||
class Process {
|
||||
public:
|
||||
static std::string execute(const std::string &cmd);
|
||||
};
|
||||
|
||||
|
||||
#endif //EQEMU_PROCESS_H
|
||||
@ -738,3 +738,18 @@ bool Strings::ToBool(std::string bool_string)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns a random string of specified length
|
||||
std::string Strings::Random(size_t length)
|
||||
{
|
||||
auto randchar = []() -> char {
|
||||
const char charset[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
const size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[static_cast<size_t>(std::rand()) % max_index];
|
||||
};
|
||||
std::string str(length, 0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -112,6 +112,7 @@ public:
|
||||
static uint32 TimeToSeconds(std::string time_string);
|
||||
static bool ToBool(std::string bool_string);
|
||||
static inline bool EqualFold(const std::string &string_one, const std::string &string_two) { return strcasecmp(string_one.c_str(), string_two.c_str()) == 0; }
|
||||
static std::string Random(size_t length);
|
||||
|
||||
template<typename T>
|
||||
static std::string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user