Скрипт умирает, когда родительский процесс прекращен

Возможно, вместо системного init вызывается сеанс init. Попробуйте это, отключив переменную UPSTART_SESSION

env -u UPSTART_SESSION initctl list
env -u UPSTART_SESSION initctl start uptest

и т. Д.

1
18.09.2018, 15:57
2 ответа

В тестовой системе Centos 7 через

$ sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
$ sudo yum install dotnet-sdk-2.1

, что приводит к установке dotnet-sdk-2.1-2.1.400-1.x86_64с тестовым кодом

using System;
using System.Diagnostics;
using System.ComponentModel;
namespace myApp {
    class Program {
        static void Main(string[] args) {
            var process = new Process();
            process.EnableRaisingEvents = true; // to avoid [defunct] sh processes
            process.StartInfo.FileName = "/var/tmp/foo";
            process.StartInfo.Arguments = "";
            process.StartInfo.UseShellExecute = true;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            process.WaitForExit(10000);
            if (process.HasExited) {
                Console.WriteLine("Exit code: " + process.ExitCode);
            } else {
                Console.WriteLine("Child process still running after 10 seconds");
            }
        }
    }
}

и сценарий оболочки как /var/tmp/fooи straceостанавливаются и показывают, что /var/tmp/fooвыполняется через xdg-open, что в моей системе делает... Я не уверен, что, это кажется ненужным усложнением.

$ strace -o foo -f dotnet run
Child process still running after 10 seconds
^C
$ grep /var/tmp/foo foo
25907 execve("/usr/bin/xdg-open", ["/usr/bin/xdg-open", "/var/tmp/foo"], [/* 37 vars */] <unfinished...>
...

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

            process.StartInfo.UseShellExecute = false;

с этим набором straceпоказывает, что /var/tmp/fooзапускается через (гораздо более простой)execve(2)вызов:

26268 stat("/var/tmp/foo", {st_mode=S_IFREG|0755, st_size=37,...}) = 0
26268 access("/var/tmp/foo", X_OK)      = 0
26275 execve("/var/tmp/foo", ["/var/tmp/foo"], [/* 37 vars */] <unfinished...>

и что.NET отказывается выходить:

$ strace -o foo -f dotnet run
Child process still running after 10 seconds
^C^C^C^C^C^C^C^C

, потому что fooзаменяется чем-то, что игнорирует большинство сигналов (, особенно не USR2, или всегда есть KILL(, но избегайте этого!)):

$ cat /var/tmp/foo
#!/bin/sh
exec /var/tmp/stayin-alive
$ cat /var/tmp/stayin-alive
#!/usr/bin/perl
use Sys::Syslog;
for my $s (qw(HUP INT QUIT PIPE ALRM TERM CHLD USR1)) {
   $SIG{$s} = \&shandle;
}
openlog( 'stayin-alive', 'ndelay,pid', LOG_USER );
while (1) {
    syslog LOG_NOTICE, "oh oh oh oh oh stayin alive";
    sleep 7;
}
sub shandle {
    syslog LOG_NOTICE, "nice try - @_";
}

демонизировать

С процессом, который отделяет себя от родителя и сценарием оболочки, который запускает несколько команд (, которые, надеюсь, эквивалентны вашим предполагаемымapt-get update; apt-get upgrade)

$ cat /var/tmp/a-few-things
#!/bin/sh
sleep 17 ; echo a >/var/tmp/output ; echo b >/var/tmp/output

мы можем изменить программу.NET для запуска/var/tmp/solitary /var/tmp/a-few-things

            process.StartInfo.FileName = "/var/tmp/solitary";
            process.StartInfo.Arguments = "/var/tmp/a-few-things";
            process.StartInfo.UseShellExecute = false;

который при запуске приводит к довольно быстрому завершению программы.NET

$ dotnet run
Exit code: 0

и, наконец, файл /var/tmp/outputдействительно содержит две строки, написанные процессом, который не был уничтожен, когда программа.NET отсутствовала.

Вы, вероятно, должны где-то сохранить вывод команд APT, а также может понадобиться что-то, чтобы два (или больше! )обновления не попытка запуска в одно и то же время и т. д. Эта версия не останавливается на вопросы и игнорирует любые TERMсигналы (INT, возможно, также необходимо игнорировать ).

#!/bin/sh
trap '' TERM
set -e
apt-get --yes update
apt-get --yes upgrade
1
27.01.2020, 23:23

Используйте crontab (или)(не mono/.net )для планирования задач.

Нормальные параметры;

  • nohup my.sh &
  • экран -дм -С мой мыш.ш
  • tmux new -d -s my my.sh
  • сервис мой запуск / systemctl запуск мой
  • Ctrl+Z, bg, отречься
2
27.01.2020, 23:23

Теги

Похожие вопросы