2014-12-09 4 views
6

Vielleicht fehlt mir gerade etwas offensichtlich in der System.Process API (http://hackage.haskell.org/package/process), aber es scheint nicht zu unterstützen, die rohe PID eines Prozesses erstellt. Die API gibt normalerweise einen ProcessHandle zurück, der leicht genug verwendet werden kann, aber dies scheint nicht die Anforderungen einer Bereitstellung zu erfüllen.Wie erhalte ich die Prozess-ID eines erstellten Prozesses in Haskell?

Ich habe einen Fall, in dem ich einen lang andauernden Prozess zum Laichen möge, melden Sie sich den PID es verwendet wird, und in der Lage sein, automatisch zu einem späteren Zeitpunkt wieder zu kommen (Tage, Wochen, Monate) und töte das alte Verfahren und Wieder Starten Sie mit einem neuen Prozess. Ich bin mir sicher, dass es mehrere Möglichkeiten gibt, dieses Auto-Deploy-and-Restart durchzuführen, aber PIDs schienen der einfachste Weg zu sein, ohne zu viel plattformabhängigen Code zu verwenden.

Ich bin offen für andere Vorschläge zu meinem zugrunde liegenden Problem, aber es scheint mir seltsam, dass ich keine direkten PID-Referenzen (oder eine Möglichkeit, sie zu konvertieren) in der Prozess-API finden kann. Dies scheint ein Versehen der API zu sein.

+0

Können Sie das ['unix'] (http://hackage.haskell.org/package/unix-2.7.0.1/docs/System-Posix-Process.html) Paket anstelle von' process' verwenden? –

+0

... oder ['Win32'] (http://hackage.haskell.org/package/Win32-2.2.2.0/docs/System-Win32-Process.html). Der allgemeine Punkt ist, dass die OS-spezifischen APIs im Allgemeinen leistungsfähiger als die plattformübergreifenden sind, da plattformübergreifende nur Dinge unterstützen können, die von allen Betriebssystemen unterstützt werden. –

+0

True, Betriebssystem-spezifische APIs sind in der Regel leistungsfähiger. Aber es ist ein wenig nervig, wenn _eine_ Sache deinen Code daran hindert, vollständig tragbar zu sein. – stormont

Antwort

4

Hier einige Codebeispiel ist:

import System.Process 
import System.Process.Internals 

-- | returns Just pid or Nothing if process has already exited 
getPid ph = withProcessHandle ph go 
    where 
    go ph_ = case ph_ of 
       OpenHandle x -> return $ Just x 
       ClosedHandle _ -> return Nothing 

main = do 
    (_,_,_,ph) <- createProcess $ shell "echo $$" 
    getPid ph >>= print 

Hinweis: I haven Ich habe das unter Windows getestet, aber es funktioniert unter OSX und vermutlich unter Linux.

unter Windows die Win32 package eine getProcessId-Funktion im Modul hat System.Win32.Process und den Code nach denen ich gelesen habe, sollte diese Arbeit:

import System.Win32.Process (getProcessId) 

main = do 
    (_,_,_,ph) <- createProcess $ shell "echo $$" 
    pid <- withProcessHandle ph go 
    print pid 

    where go (OpenHandle x) = fmap Just $ getProcessId x 
     go (ClosedHandle _) = return Nothing 

Der Code, den ich dies auf für interruptProcessGroupOf der Code am stützen (link)

+0

Dies scheint auf vernünftige Weise (auch unter Windows verifiziert) zu funktionieren, ohne die Abstraktion (IMO) wirklich zu brechen. Das sieht auch ähnlich aus wie dieser alte Postversand: https://www.haskell.org/pipermail/haskell-cafe/2012-Oktober/104028.html – stormont

+0

Bei weiterer Überprüfung bin ich mir der Ergebnisse nicht so sicher. Ich habe dies in $ shell "notepad" geändert, um die PID im Task Manager leichter zu finden. Sieht so aus, als würde ich verschiedene PIDs für diesen und asjos Vorschlag bekommen, von denen keiner passt. – stormont

+0

Scratch das, ich hatte mich verwirrt. Ich war auf der Suche nach der PID von Notepad, aber ich habe vergessen, dass dies Shell-aufgerufen wurde, also hätte ich wirklich nach der Shell-Prozess-ID suchen müssen, die asjos Ergebnis entspricht. withProcessHandle-Ergebnisse scheinen nicht (direkt) mit dem PID-Ergebnis unter Windows übereinzustimmen; Ich erhalte Hexadezimalwerte, aber sie sind zu niedrig, um den untergeordneten Prozessen zu entsprechen. – stormont

0

Wenn alles andere fehlschlägt,

import System.Process.Internals 

und dann innerhalb der Abstraktion ProcessHandle graben. Sie möchten wahrscheinlich die PHANDLE aus der MVar extrahieren.

Beachten Sie, dass dies die Abstraktionsschicht durchbricht, die den Code portierbar zwischen den Betriebssystemen machen soll. Benutze es mit äußerster Sorgfalt und sei darauf vorbereitet, dass es neue Versionen der Bibliothek einbricht.

3

Sieht aus wie interruptProcessGroupOf in System.Process Anrufe entweder System.Posix.Process.getProcessGroupIDOf (POSIX/nicht Windows) oder System.Win32.Process.getProcessId (Windows), um die pid zu erhalten: http://git.haskell.org/packages/process.git/blob/HEAD:/System/Process.hs

+0

Können Sie den Unterschied zwischen 'getProcessGroupID' und' getProcessID' in 'System.Posix.Process' beschreiben? –

+0

Nein. Ich denke, man arbeitet für POSIX-Systeme, das andere für Windows-Systeme. Ich denke, dass System.Process geändert werden könnte, um den Code für das Abrufen der PID von interruptProcessGroupOf in eine Funktion, die Code verwenden könnte, die System.Process verwenden könnte. – asjo

+0

Ich war ein bisschen unklar. Beide der Funktionen, die ich erwähnte, befinden sich in dem Modul "System.Posix.Process", das sich von dem "getProcessId" in dem Windows-Modul unterscheidet. (Sogar anders geschrieben: 'ID' vs' Id'.) Ich * denke * es hat etwas damit zu tun, die PID des aktuellen Prozesses gegen die PID des Elternprozesses zu bekommen, aber ich verstehe die Details nicht. –

Verwandte Themen