2017-01-24 4 views
0

Ich habe das folgende Shell-Skript:Awk Syntaxfehler mit Systemaufruf

#!/bin/bash 

top -n 1 -p $(pgrep -d',' -f R) | grep R | awk '{if ($2 != "PID" && int($10) > 50) 
{ 
    kill_cmd = "echo kill " $1 " | bash -"; 
    system(kill_cmd); 
}}' 

Wenn ich den Systemaufruf auf eine print-Anweisung die resultierende Ausgabe ändern sieht aus, als ich erwarten: echo kill <some_pid> | bash - Ich bin auch in der Lage, die Ausgabe laufen von den Druckanweisungen ohne Fehler.

Der Systemaufruf Fehler aus besagt: Syntaxfehler in der Nähe von unerwartetem Token `(‘

Die Absicht des Skripts ist oben zu verwenden, bei laufender R Prozesse zu suchen und tötet sie, wenn sie mehr als 50% verwenden von der Systemspeicher.

+0

Wenn die Debug-print-Anweisung die erwartete Ausgabe erzeugt, wie Sie es sagen, dann gibt es nichts in Ihrem Skript, das die Fehlermeldung produzieren würde, die Sie sagen Sie machen also irgendwo einen Fehler bei der Diagnose/Beschreibung des Problems. Fügen Sie "print" <"kill_cmd"> "' vor dem Aufruf von system() hinzu und führen Sie dann 'cat -v script; ./script' und kopiere/füge das Ergebnis in deine Frage ein, so dass wir genau den Befehl sehen können, den du ausführst und die Ausgabe und die Fehlermeldung, die er erzeugt. –

Antwort

1

In Ihrem Fall unter Aussagen sind falsch Sie nicht echo benötigen, | und bash -

kill_cmd = "echo kill " $1 " | bash -"; 
system(kill_cmd); 

Sie können einfach verwenden (Hinweis: stellen Sie sicher, Spalte PID in $ 1, sollte es $ 2, I erraten sein)

$ top -n 1 -p $(pgrep -d',' -f R) | 
    awk '/R/ && $2 != "PID" && int($10) > 50{system("kill " $2)}' 

Wie unten

$ awk 'BEGIN{system("date")}' 
Tue Jan 24 12:41:08 IST 2017 

Statt system() jedes der Aufruf Zeit, Sie können es am Ende pipen

Entweder

$ top -n 1 -p $(pgrep -d',' -f R) | 
    awk '/R/ && $2 != "PID" && int($10) > 50{ print "echo kill " $2 }' | bash 

ODER

$ top -n 1 -p $(pgrep -d',' -f R) | 
    awk '/R/ && $2 != "PID" && int($10) > 50{ print $2 }' | xargs kill -9 

Zum Beispiel

$ awk 'BEGIN{for(i=1;i<=5;i++)print "echo test :"i; print "date"}' 
echo test :1 
echo test :2 
echo test :3 
echo test :4 
echo test :5 
date 

$ awk 'BEGIN{for(i=1;i<=5;i++)print "echo test :"i; print "date"}' | bash 
test :1 
test :2 
test :3 
test :4 
test :5 
Tue Jan 24 12:31:43 IST 2017 
0
#!/bin/bash 

eval "$( 
    top -n 1 -p $(pgrep -d',' -f R) \ 
    | awk ' 
     /R/ && $10 >= 51 && $2 != "PID" { L = L " " $1 } 
     END { if (L !~ /^$/) print "kill" L } 
     ' 
    )" 
  • eval Anruf nur einmal die Systeme über einen Sub-Shell für alle PID zu töten (töten lassen zu töten mehrere als Parameter
  • keine Notwendigkeit eines grep R von einem awk gefolgt geführt pid, awk konnte Filter mit /R/
  • einfachen Test oft als Filter anstelle einer der, wenn innere Struktur
  • gemacht werden könnte
  • hinzufügen vielleicht eine Levell von Signal (schließlich über Variable awk bestanden) für Tötungs Ebene
1

die Absicht des Skripts ist oben zu verwenden, bei laufender R Prozesse zu suchen und tötet sie, wenn sie mehr als 50% des Systemspeichers verwenden .

Zu diesem Zweck würde ich nicht pgrep noch top verwenden, und auch keine nutzlosen grep vor awk.

ps aux | awk '$11 ~/R/ && $4 > 50 { system("kill " $2) }' 

oder

ps aux | awk '$11 ~/R/ && $4 > 50 { print $2 }' | xargs kill 

Das auf Linux getestet wurde. Abhängig von der speziellen Formatierung der Ausgabe von ps in Ihrem System können die Dollar-Parameter unterschiedlich nummeriert sein (Sie könnten auch ps anweisen, ein anderes Ausgabeformat oder eine andere Prozessauswahl zu verwenden, indem Sie ein anderes Argument als aux angeben) Match ~/R/ sollte wahrscheinlich verfeinert werden, aber es ist das gleiche, das Sie verwendet haben. xargs Aufrufe kill nur einmal, nach dem Sammeln der PIDs in einer Befehlszeile, es sei denn, es gibt zu viele von ihnen, in diesem Fall xargs teilt die PIDs in eine entsprechende Anzahl von kill Aufrufe (in diesem Fall unmöglich, da Sie nicht zehn haben können Prozesse, von denen jeder mehr als 50% des Systemspeichers verbraucht ...)

+0

Große Lösung; Danke. Weißt du, warum mein Systemanruf fehlgeschlagen ist? –

+0

In der Tat, nein. Ich war nicht in der Lage, den Fehler zu reproduzieren, und ich vermute, dass es durch einen gelegentlichen Tippfehler verursacht wurde, wie ein unausgewogenes Zitat oder ähnliches. Aber wenn Sie Ihre Befehlszeile vereinfachen, verringern Sie auch die Wahrscheinlichkeit solcher obskuren Fehler. Und bitte vergiss nicht, die Antwort zu akzeptieren, wenn es dir gefällt ... – Dario