Возможно, вместо системного init вызывается сеанс init. Попробуйте это, отключив переменную UPSTART_SESSION
env -u UPSTART_SESSION initctl list
env -u UPSTART_SESSION initctl start uptest
и т. Д.
В тестовой системе 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
Используйте crontab (или)(не mono/.net )для планирования задач.
Нормальные параметры;