Как заставить RUST изящно работать в фоновом режиме и демонстрировать - PullRequest
0 голосов
/ 08 мая 2020

Это то, чего я хочу достичь

root> ./webserver start   // Does not block the terminal after startup, runs in the background and the process is guarded
root> 

Моя текущая логика реализации :

Logi c работает в фоновом режиме
 use std::process::Command;
use std::thread;
use std::env;
use std::time::Duration;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() == 2 {
        if &args[1] == "start" {
            // Main process start child process
            let child = Command::new(&args[0])
                .spawn().expect("Child process failed to start.");
            println!("child pid: {}", child.id());
            // Main process exit
        }
    } else {Is there any more elegant approach? Looking forward to your reply
        // Main business logic
        run webserver
    }
}

Таким образом, ржавчина будет работать в фон, не блокируя терминал, но информация, напечатанная ржавчиной в фоновом режиме, будет по-прежнему отображаться на терминале, и текущая программа ржавчины выйдет при выходе из терминала

Логика демона процесса

Моя идея состоит в том, чтобы контролировать выход сигнал системы и не обрабатывает запрос на выход

SIGHUP       1          /* Hangup (POSIX).  */                  
SIGINT       2          /* Interrupt (ANSI).  */                       
SIGQUIT      3          /* Quit (POSIX).  */                        
SIGTERM      15         /* Termination (ANSI).  */               

код:

use signal_hook::{iterator::Signals, SIGHUP,SIGINT,SIGQUIT,SIGTERM};
use std::{thread, time::Duration};
pub fn process_daemon() {
    let signals = match Signals::new(&[SIGHUP,SIGINT,SIGQUIT,SIGTERM]) {
        Ok(t) => t,
        Err(e) => panic!(e),
    };Is there any more elegant approach? Looking forward to your reply

    thread::spawn(move || {
        for sig in signals.forever() {
            println!("Received signal {:?}", sig);
        }
    });

    thread::sleep(Duration::from_secs(2));
}

Есть ли более элегантный подход? С нетерпением жду вашего ответа.

1 Ответ

2 голосов
/ 08 мая 2020

TL; DR: если вы действительно хотите, чтобы ваш процесс работал как служба (и никогда не завершал работу), возможно, выполните работу по настройке диспетчера служб. В противном случае, просто позвольте этому быть нормальным процессом.

Демонизация процесса

Сразу же следует заметить, что большинство соображений о демонизации не имеют ничего общего с использовать Rust в качестве языка и больше о:

  1. Базовая система, на которую нацелены ваши процессы
  2. Точное поведение ваших процессов-демонов после их создания

Глядя на ваш вопрос, кажется, вы уже поняли большую часть этого. К сожалению, чтобы правильно ответить на ваш вопрос, мы должны немного углубиться в тонкости процессов и то, как ими управлять. Следует отметить, что существующие «сервисные» менеджеры - отличное решение, если вас устраивает значительная платформа зависимость в вашей инфраструктуре запуска.

Как видите, нет простого подвига, если вы хотите иметь простое развертывание, которое просто работает (при условии, что оно скомпилировано для соответствующей системы). Это просто менеджеры по обслуживанию без оборудования. Если вы хотите поддерживать виртуальные среды, вам придется подумать о сервисах Kubernetes, dockerizing и т. Д. c.

Эти инструменты существуют, потому что есть много соображений по управлению длительным процессом в системе:

  • Должен ли мой демон вести себя как служба и возродиться в случае его убийства (или при перезагрузке системы)? Приведенные выше инструменты позволят это сделать.
  • Если это служба, должен ли мой демон иметь связанные с ней состояния состояния, чтобы помогать в обслуживании? Это может помочь в управлении отключениями и создании инструментов для горизонтального масштабирования.
  • Если демон не должен быть службой (маловероятно в вашем случае, учитывая имя вашего двоичного файла), возникает еще больше вопросов: должен ли он быть прикреплен к родительский процесс? Должен ли он быть присоединен к группе процессов входа в систему?

Я предполагаю, что для вашего процесса, учитывая, насколько сложным он может стать, просто запустите процесс напрямую. Не демонизируйте вообще.

Для тестирования (если вы находитесь в среде, подобной unix), вы можете запустить свой процесс в фоновом режиме:

./webserver start &

Это запустится новый процесс в фоновом режиме, но присоедините его к списку процессов вашей оболочки. Это может быть удобно для тестирования, потому что, если эта оболочка исчезнет, ​​система очистит эти присоединенные процессы вместе с ней.

Вышеупомянутое будет направлять дескрипторы файлов stderr и stdout обратно в ваш терминал и распечатывать их. Если вы используете sh, чтобы избежать этого, вы всегда можете перенаправить вывод в другое место.

Отключение сигналов для такого процесса, как этот, мне не кажется правильным подходом. Сохраните эти сигналы, чтобы изящно выйти из процесса, когда вам нужно сохранить состояние или отправить клиенту сообщение о завершении. Если вы сделаете это, ваш демон будет уничтожен только kill -9 <pid>, перезагрузкой или обнаружением нестандартного сигнала, который вы не переопределили, поведение которого по умолчанию должно завершиться.

...