Skip to content

Commit

Permalink
feat: Improve execution modes on unix
Browse files Browse the repository at this point in the history
The way the agent is executed has been simplified. Additionally, the use of a
PID file to check if the agent is running has been replaced with a
wazuh-agent.lock file, which remains write-locked during the agent's execution.
This prevents another instance from running. The `--start` and `--run` options
have been removed, and the process now runs in the foreground without any
options. The `--stop` and `--restart` options have also been removed.
  • Loading branch information
sdvendramini committed Nov 20, 2024
1 parent 8dac1c2 commit 95ab86f
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 122 deletions.
6 changes: 3 additions & 3 deletions src/agent/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ int main(int argc, char* argv[])
{
SetDispatcherThread();
}
else if (cmdParser.OptionExists(OPT_RUN) || cmdParser.OptionExists(OPT_START))
else if (cmdParser.OptionExists(OPT_HELP))
{
StartAgent(configFile);
PrintHelp();
}
else
{
PrintHelp();
StartAgent(configFile);
}

return 0;
Expand Down
2 changes: 0 additions & 2 deletions src/agent/src/process_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#include <string>

/// Command-line options
static const auto OPT_RUN {"--run"};
static const auto OPT_START {"--start"};
static const auto OPT_STATUS {"--status"};
static const auto OPT_STOP {"--stop"};
static const auto OPT_RESTART {"--restart"};
Expand Down
46 changes: 9 additions & 37 deletions src/agent/src/process_options_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,26 @@
#include <thread>
#include <vector>

void RestartAgent(const std::string& configFile)
void RestartAgent([[maybe_unused]] const std::string& configFile)
{
StopAgent();

std::this_thread::sleep_for(std::chrono::seconds(1)); // NOLINT

StartAgent(configFile);
std::cout << "not implemented on Unix.\n";
}

void StartAgent(const std::string& configFile)
{
pid_t pid = unix_daemon::PIDFileHandler::ReadPIDFromFile();
if (pid > 0)
unix_daemon::LockFileHandler lockFileHandler = unix_daemon::GenerateLockFile();

if (!lockFileHandler.isLockFileCreated())
{
std::cout << "wazuh-agent already running\n";
return;
}
else if (pid < 0)
{
std::cout << "Error reading pid file\n";
return;
}

LogInfo("Starting wazuh-agent");
unix_daemon::PIDFileHandler handler = unix_daemon::GeneratePIDFile();
Agent agent(configFile);
agent.Run();

lockFileHandler.removeLockFile();
}

void StatusAgent()
Expand All @@ -47,24 +40,7 @@ void StatusAgent()

void StopAgent()
{
LogInfo("Stopping wazuh-agent");
pid_t pid = unix_daemon::PIDFileHandler::ReadPIDFromFile();

if (pid < 0)
{
std::cout << "Error reading pid file\n";
return;
}

if (!kill(pid, SIGTERM))
{
LogInfo("Wazuh-agent terminated");
}
else
{
kill(pid, SIGKILL);
LogInfo("Wazuh-agent killed");
}
std::cout << "not implemented on Unix.\n";
}

void PrintHelp()
Expand All @@ -74,14 +50,10 @@ void PrintHelp()
std::cout << "Usage: wazuh-agent [options]\n";
std::cout << "\n";
std::cout << "Options:\n";
std::cout << " " << OPT_RUN << " Start wazuh-agent\n";
std::cout << " " << OPT_START << " Start wazuh-agent daemon\n";
std::cout << " " << OPT_STATUS << " Get wazuh-agent daemon status\n";
std::cout << " " << OPT_STOP << " Stop wazuh-agent daemon\n";
std::cout << " " << OPT_RESTART << " Restart wazuh-agent daemon\n";
std::cout << " " << OPT_REGISTER_AGENT << " Register wazuh-agent\n";
std::cout << " " << OPT_CONFIG_FILE << " Specify the full path of the configuration file (optional).\n";
std::cout << " Used with " << OPT_RUN << ", " << OPT_RESTART << ", or "
std::cout << " Can be used when running the application normally or with"
<< OPT_REGISTER_AGENT << ".\n";
std::cout << " " << OPT_HELP << " This help message\n";
}
Expand Down
74 changes: 29 additions & 45 deletions src/agent/src/unix_daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,22 @@
#include <cerrno>
#include <filesystem>
#include <fstream>
#include <sys/file.h>

namespace fs = std::filesystem;

namespace unix_daemon
{
constexpr std::string_view PID_PATH = "var/run";
constexpr std::string_view LOCK_PATH = "var/run";

PIDFileHandler::PIDFileHandler()
LockFileHandler::LockFileHandler()
: m_lockFileCreated(createLockFile())
{
writePIDFile();
}

PIDFileHandler::~PIDFileHandler()
bool LockFileHandler::removeLockFile() const
{
removePIDFile();
}

bool PIDFileHandler::removePIDFile() const
{
const std::string filePath = fmt::format("{}/{}/wazuh-agent.pid", GetExecutablePath(), PID_PATH);
const std::string filePath = fmt::format("{}/{}/wazuh-agent.lock", GetExecutablePath(), LOCK_PATH);
try
{
std::filesystem::remove(filePath);
Expand All @@ -37,7 +33,7 @@ namespace unix_daemon
}
}

bool PIDFileHandler::createDirectory(const std::string_view relativePath) const
bool LockFileHandler::createDirectory(const std::string_view relativePath) const
{
try
{
Expand All @@ -59,49 +55,34 @@ namespace unix_daemon
}
}

bool PIDFileHandler::writePIDFile() const
bool LockFileHandler::createLockFile() const
{
const std::string path = fmt::format("{}/{}", GetExecutablePath(), PID_PATH);
const std::string path = fmt::format("{}/{}", GetExecutablePath(), LOCK_PATH);
createDirectory(path);

const std::string filename = fmt::format("{}/{}/wazuh-agent.pid", GetExecutablePath(), PID_PATH);
std::ofstream file(filename);
const std::string filename = fmt::format("{}/wazuh-agent.lock", path);

if (!file.is_open())
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, cppcoreguidelines-avoid-magic-numbers)
int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
{
LogCritical("Unable to write PID file: {}. Error: {} ({})", filename.c_str(), errno, std::strerror(errno));
LogError("Unable to open lock file: {}. Error: {} ({})", filename.c_str(), errno, std::strerror(errno));
return false;
}

file << getpid();
file.close();

return true;
}

pid_t PIDFileHandler::ReadPIDFromFile()
{
const std::string filename = fmt::format("{}/{}/wazuh-agent.pid", GetExecutablePath(), PID_PATH);
std::ifstream file(filename);

if (!file.is_open())
if (flock(fd, LOCK_EX | LOCK_NB) == -1)
{
return 0;
LogError("Unable to lock lock file: {}. Error: {} ({})", filename.c_str(), errno, std::strerror(errno));
close(fd);
return false;
}

pid_t value {};
file >> value;

if (file.fail())
{
LogError("Error reading PID file: {}({})", filename.c_str(), errno, std::strerror(errno));
return -1;
}
LogDebug("Lock file created: {}", filename);

return value;
return true;
}

std::string PIDFileHandler::GetExecutablePath()
std::string LockFileHandler::GetExecutablePath()
{
std::vector<char> pathBuffer(PATH_MAX);
const ssize_t len = readlink("/proc/self/exe", pathBuffer.data(), pathBuffer.size() - 1);
Expand All @@ -118,18 +99,21 @@ namespace unix_daemon
}
}

PIDFileHandler GeneratePIDFile()
LockFileHandler GenerateLockFile()
{
return {};
}

std::string GetDaemonStatus()
{
const pid_t pid = PIDFileHandler::ReadPIDFromFile();
if (pid == 0)
LockFileHandler lockFileHandler = GenerateLockFile();

if (!lockFileHandler.isLockFileCreated())
{
return "stopped";
return "running";
}
return "running";

lockFileHandler.removeLockFile();
return "stopped";
}
} // namespace unix_daemon
59 changes: 24 additions & 35 deletions src/agent/src/unix_daemon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,48 @@

namespace unix_daemon
{
/// @class PIDFileHandler class
/// @brief Handles the creation, reading, and deletion of PID files for managing process IDs
class PIDFileHandler
/// @class LockFileHandler class
/// @brief Handles the creation and deletion of lock files to prevent multiple instances of wazuh agent running
class LockFileHandler
{
public:
/// @brief Default constructor
/// @details Creates a PID file when the instance is created
PIDFileHandler();
/// @details Creates a lock file when the instance is created
LockFileHandler();

/// @brief Destructor
/// @details Deletes the PID file
~PIDFileHandler();
/// @brief Checks if the lock file has been successfully created
/// @return True if the lock file is created, false otherwise
bool isLockFileCreated() const
{
return m_lockFileCreated;
}

/// @brief Copy constructor
PIDFileHandler(const PIDFileHandler&) = delete;

/// @brief Copy assignment operator
PIDFileHandler& operator=(const PIDFileHandler&) = delete;

/// @brief Move constructor
PIDFileHandler(PIDFileHandler&&) = default;

/// @brief Move assignment operator
PIDFileHandler& operator=(PIDFileHandler&&) = default;

/// @brief Reads the process ID from the PID file
/// @return The process ID from the PID file
static pid_t ReadPIDFromFile();
/// @brief Removes the lock file
/// @return True if the file is removed, false otherwise
bool removeLockFile() const;

private:
/// @brief Creates the directory path for the PID file
/// @param relativePath The relative path for the PID file
/// @brief Creates the directory path for the lock file
/// @param relativePath The relative path for the lock file
/// @return True if the directory is created, false otherwise
bool createDirectory(const std::string_view relativePath) const;

/// @brief Writes the current process ID to the PID file
/// @return True if the PID file is written, false otherwise
bool writePIDFile() const;

/// @brief Removes the PID file
/// @return True if the PID file is removed, false otherwise
bool removePIDFile() const;
/// @brief Creates the lock file
/// @return True if the lock file is created, false otherwise
bool createLockFile() const;

/// @brief Gets the executable path
/// @return The executable path
static std::string GetExecutablePath();

bool m_lockFileCreated;
};

/// @brief Gets the status of the daemon
/// @return A string indicating whether the daemon is "running" or "stopped"
std::string GetDaemonStatus();

/// @brief Generates a PID file for the daemon
/// @return A PIDFileHandler object
PIDFileHandler GeneratePIDFile();
/// @brief Generates a lock file for the daemon
/// @return A LockFileHandler object
LockFileHandler GenerateLockFile();
} // namespace unix_daemon

0 comments on commit 95ab86f

Please sign in to comment.