refactor(script): Better handling of tail scripts
This commit is contained in:
parent
c959d2c7c6
commit
6cae06c4dc
6 changed files with 92 additions and 43 deletions
|
@ -10,6 +10,7 @@ namespace modules
|
|||
static constexpr auto TAG_OUTPUT = "<output>";
|
||||
|
||||
std::unique_ptr<Builder> builder;
|
||||
std::unique_ptr<Command> command;
|
||||
|
||||
std::string exec;
|
||||
bool tail = false;
|
||||
|
@ -28,6 +29,7 @@ namespace modules
|
|||
public:
|
||||
explicit ScriptModule(const std::string& name);
|
||||
|
||||
void start();
|
||||
bool update();
|
||||
bool build(Builder *builder, const std::string& tag);
|
||||
std::string get_output();
|
||||
|
|
|
@ -34,6 +34,7 @@ class Command
|
|||
int get_stdout(int);
|
||||
// int get_stdin(int);
|
||||
|
||||
// pid_t get_pid();
|
||||
// int get_exit_status();
|
||||
pid_t get_pid();
|
||||
bool is_running();
|
||||
int get_exit_status();
|
||||
};
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace io
|
|||
|
||||
std::string read(int read_fd, int bytes_to_read = -1);
|
||||
std::string read(int read_fd, int bytes_to_read, int &bytes_read_loc, int &status_loc);
|
||||
std::string readline(int read_fd, int &bytes_read);
|
||||
std::string readline(int read_fd);
|
||||
|
||||
int write(int write_fd, const std::string& data);
|
||||
|
|
|
@ -13,7 +13,9 @@ ScriptModule::ScriptModule(const std::string& name_)
|
|||
this->exec = config::get<std::string>(name(), "exec");
|
||||
this->tail = config::get<bool>(name(), "tail", this->tail);
|
||||
|
||||
if (!this->tail)
|
||||
if (this->tail)
|
||||
this->interval = 0s;
|
||||
else
|
||||
this->interval = std::chrono::duration<double>(config::get<float>(name(), "interval", 1));
|
||||
|
||||
this->click_left = config::get<std::string>(name(), "click-left", "");
|
||||
|
@ -27,38 +29,67 @@ ScriptModule::ScriptModule(const std::string& name_)
|
|||
// Add formats and elements {{{
|
||||
this->formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, { TAG_OUTPUT });
|
||||
// }}}
|
||||
|
||||
this->counter = 0;
|
||||
}
|
||||
|
||||
void ScriptModule::start()
|
||||
{
|
||||
this->TimerModule::start();
|
||||
|
||||
if (!this->tail)
|
||||
return;
|
||||
|
||||
// Start the tail script in a separate thread {{{
|
||||
this->threads.push_back(std::thread([&]{
|
||||
while (this->enabled() && (!this->command || !this->command->is_running())) {
|
||||
log_debug("Executing command: "+ this->exec);
|
||||
this->counter++;
|
||||
this->command = std::make_unique<Command>("/usr/bin/env\nsh\n-c\n"
|
||||
+ string::replace_all(this->exec, "%counter%", std::to_string(this->counter)));
|
||||
this->command->exec(true);
|
||||
}
|
||||
}));
|
||||
// }}}
|
||||
}
|
||||
|
||||
bool ScriptModule::update()
|
||||
{
|
||||
this->counter++;
|
||||
this->output.clear();
|
||||
int bytes_read;
|
||||
|
||||
if (this->tail) {
|
||||
if (!this->command)
|
||||
return false;
|
||||
if (!io::poll_read(this->command->get_stdout(PIPE_READ), 100))
|
||||
return false;
|
||||
this->output = io::readline(this->command->get_stdout(PIPE_READ), bytes_read);
|
||||
return bytes_read > 0;
|
||||
}
|
||||
|
||||
try {
|
||||
std::string buf;
|
||||
this->counter++;
|
||||
this->output.clear();
|
||||
|
||||
auto execline = string::replace_all(this->exec, "%counter%", std::to_string(this->counter));
|
||||
auto command = std::make_unique<Command>("/usr/bin/env\nsh\n-c\n"+ execline);
|
||||
this->command = std::make_unique<Command>("/usr/bin/env\nsh\n-c\n"
|
||||
+ string::replace_all(this->exec, "%counter%", std::to_string(this->counter)));
|
||||
this->command->exec(false);
|
||||
|
||||
command->exec(false);
|
||||
|
||||
while (!(buf = io::readline(command->get_stdout(PIPE_READ))).empty() || (this->tail && this->enabled())) {
|
||||
this->output.append(buf + "\n");
|
||||
|
||||
if (this->tail) {
|
||||
this->broadcast();
|
||||
this->output.clear();
|
||||
}
|
||||
while (true) {
|
||||
auto buf = io::readline(this->command->get_stdout(PIPE_READ), bytes_read);
|
||||
if (bytes_read <= 0)
|
||||
break;
|
||||
this->output.append(buf +"\n");
|
||||
}
|
||||
|
||||
command->wait();
|
||||
if (this->command)
|
||||
this->command->wait();
|
||||
} catch (CommandException &e) {
|
||||
log_error(e.what());
|
||||
} catch (proc::ExecFailure &e) {
|
||||
log_error(e.what());
|
||||
}
|
||||
|
||||
return !this->output.empty();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ScriptModule::get_output()
|
||||
|
@ -66,17 +97,19 @@ std::string ScriptModule::get_output()
|
|||
if (this->output.empty())
|
||||
return "";
|
||||
|
||||
auto counter_str = std::to_string(this->counter);
|
||||
|
||||
if (!this->click_left.empty())
|
||||
this->builder->cmd(Cmd::LEFT_CLICK, string::replace_all(this->click_left, "%counter%", std::to_string(this->counter)));
|
||||
this->builder->cmd(Cmd::LEFT_CLICK, string::replace_all(this->click_left, "%counter%", counter_str));
|
||||
if (!this->click_middle.empty())
|
||||
this->builder->cmd(Cmd::MIDDLE_CLICK, string::replace_all(this->click_middle, "%counter%", std::to_string(this->counter)));
|
||||
this->builder->cmd(Cmd::MIDDLE_CLICK, string::replace_all(this->click_middle, "%counter%", counter_str));
|
||||
if (!this->click_right.empty())
|
||||
this->builder->cmd(Cmd::RIGHT_CLICK, string::replace_all(this->click_right, "%counter%", std::to_string(this->counter)));
|
||||
this->builder->cmd(Cmd::RIGHT_CLICK, string::replace_all(this->click_right, "%counter%", counter_str));
|
||||
|
||||
if (!this->scroll_up.empty())
|
||||
this->builder->cmd(Cmd::SCROLL_UP, string::replace_all(this->scroll_up, "%counter%", std::to_string(this->counter)));
|
||||
this->builder->cmd(Cmd::SCROLL_UP, string::replace_all(this->scroll_up, "%counter%", counter_str));
|
||||
if (!scroll_down.empty())
|
||||
this->builder->cmd(Cmd::SCROLL_DOWN, string::replace_all(this->scroll_down, "%counter%", std::to_string(this->counter)));
|
||||
this->builder->cmd(Cmd::SCROLL_DOWN, string::replace_all(this->scroll_down, "%counter%", counter_str));
|
||||
|
||||
this->builder->node(this->Module::get_output());
|
||||
|
||||
|
|
|
@ -146,10 +146,14 @@ int Command::get_stdout(int c) {
|
|||
// return this->stdin[c];
|
||||
// }
|
||||
|
||||
// pid_t Command::get_pid() {
|
||||
// return this->fork_pid;
|
||||
// }
|
||||
pid_t Command::get_pid() {
|
||||
return this->fork_pid;
|
||||
}
|
||||
|
||||
// int Command::get_exit_status() {
|
||||
// return this->fork_status;
|
||||
// }
|
||||
bool Command::is_running() {
|
||||
return proc::wait_for_completion_nohang(this->fork_pid, &this->fork_status) > -1;
|
||||
}
|
||||
|
||||
int Command::get_exit_status() {
|
||||
return this->fork_status;
|
||||
}
|
||||
|
|
|
@ -130,10 +130,9 @@ namespace io
|
|||
return read(read_fd, bytes_to_read, bytes_read, status);
|
||||
}
|
||||
|
||||
std::string readline(int read_fd)
|
||||
std::string readline(int read_fd, int &bytes_read)
|
||||
{
|
||||
std::stringstream buffer;
|
||||
int bytes_read;
|
||||
char c;
|
||||
|
||||
while ((bytes_read = ::read(read_fd, &c, 1)) > 0) {
|
||||
|
@ -145,9 +144,17 @@ namespace io
|
|||
get_logger()->debug("Reached EOF");
|
||||
} else if (bytes_read == -1) {
|
||||
get_logger()->debug("Read failed");
|
||||
} else {
|
||||
return string::strip_trailing_newline(buffer.str());
|
||||
}
|
||||
|
||||
return string::strip_trailing_newline(buffer.str());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string readline(int read_fd)
|
||||
{
|
||||
int bytes_read;
|
||||
return readline(read_fd, bytes_read);
|
||||
}
|
||||
|
||||
int write(int write_fd, const std::string& data) {
|
||||
|
@ -163,21 +170,22 @@ namespace io
|
|||
return io::write(write_fd, data);
|
||||
}
|
||||
|
||||
void tail(int read_fd, int writeback_fd)
|
||||
void tail(int read_fd, std::function<void(std::string)> callback)
|
||||
{
|
||||
std::string line;
|
||||
|
||||
while (false == (line = io::readline(read_fd)).empty()) {
|
||||
io::writeline(writeback_fd, line);
|
||||
std::cout << '\n';
|
||||
int bytes_read;
|
||||
while (true) {
|
||||
auto line = io::readline(read_fd, bytes_read);
|
||||
if (bytes_read <= 0)
|
||||
break;
|
||||
callback(line);
|
||||
}
|
||||
}
|
||||
|
||||
void tail(int read_fd, std::function<void(std::string)> callback)
|
||||
void tail(int read_fd, int writeback_fd)
|
||||
{
|
||||
std::string line;
|
||||
while (false == (line = io::readline(read_fd)).empty())
|
||||
callback(line);
|
||||
tail(read_fd, [&writeback_fd](std::string data){
|
||||
io::writeline(writeback_fd, data);
|
||||
});
|
||||
}
|
||||
|
||||
bool poll_read(int fd, int timeout_ms) {
|
||||
|
|
Loading…
Reference in a new issue