В настоящее время я работаю над сценарием Ruby, который должен выполнять различные задачи на довольно длинном списке хостов. Я использую гем net -s sh для связи с этими хостами. Дело в том, что, похоже, существуют некоторые условия, при которых время ожидания net -s sh истекает без создания исключения. Как известно, скрипт только один раз смог завершить sh прогон. В большинстве случаев скрипты просто зависают в какой-то момент, даже не вызывая исключения или ничего не делая.
Я думал о запуске всех задач, которые могут истекать по таймауту, в разных потоках, передавая им указатель на некоторую переменную, которую они могут изменить после успешного завершения задачи, а затем проверять эту переменную в течение заданного количества времени. Если к тому времени задача не будет завершена, вызовите исключение в основном потоке, которое я могу где-то перехватить.
Я впервые пишу что-то в Ruby. Чтобы наглядно продемонстрировать, чего я хочу достичь sh, вот что я бы сделал в C ++:
void perform_long_running_task(bool* finished);
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func);
int seconds_to_wait {5};
int seconds_task_takes{6};
int main() {
start_task_and_throw_on_timeout(seconds_to_wait, &perform_long_running_task);
// do other stuff
return 0;
}
void perform_long_running_task(bool* finished){
// Do something that may possible timeout..
std::this_thread::sleep_for(std::chrono::seconds(seconds_task_takes));
// Finished..
*finished = true;
}
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func){
bool finished {false};
std::thread task(func, &finished);
while (secs > 0){
std::this_thread::sleep_for(std::chrono::seconds(1));
secs--;
if (finished){
task.join();
return;
}
}
throw std::exception();
}
Здесь, когда 'seconds_task_takes' больше, чем 'seconds_to_wait', исключение составляет брошен в основной поток. Если задача завершается вовремя, все идет гладко.
Однако мне нужно написать свою программу на языке сценариев c Dynami, который может работать где угодно и не требует компиляции. Я был бы очень рад любому совету о том, как я могу написать что-то вроде приведенного выше кода в Ruby.
Заранее большое спасибо :)
edit: в этом примере я добавил std :: function для start_task_and_throw_timeout, чтобы его можно было повторно использовать для всех подобных функций