Wie kann ich Probleme mit exec() debuggen?

Lesezeit: 10 Minuten

Wie kann ich Probleme mit exec debuggen
carcargi

Der Befehl exec funktioniert auf meinem Server nicht, er macht nichts, ich habe safe_mode deaktiviert und überprüft, ob alle Konsolenbefehle funktionieren, ich habe es mit absoluten Pfaden versucht. Ich habe die Berechtigungen für die Anwendungen überprüft und alle Anwendungen, die ich benötige, haben Ausführungsberechtigungen. Ich weiß nicht, was ich sonst tun soll, hier sind die Codes, die ich ausprobiert habe.

echo exec('/usr/bin/whoami');

echo exec('whoami');

exec('whoami 2>&1',$output,$return_val);
if($return_val !== 0) {
    echo 'Error<br>';
    print_r($output);   
}

exec('/usr/bin/whoami 2>&1',$output,$return_val);
if($return_val !== 0) {
    echo 'Error<br>';
    print_r($output);   
}

Die letzten beiden Codes werden angezeigt:

Error
Array ( )

Ich habe den Serverdienst kontaktiert und sie können mir nicht helfen, sie wissen nicht, warum der exec-Befehl nicht funktioniert.

  • Was meinst du mit “funktioniert nicht”? Irgendeine Fehlerausgabe?

    – Touki

    30. August 2012 um 14:38 Uhr

  • Fehlereinstellungen display_errors = 1 und error_report = E_ALL? (Beachten Sie, dass Sie auf Live-Systemen keine Fehler anzeigen sollten. Deaktivieren Sie es, wenn Sie fertig sind.)

    – KingCrunch

    30. August 2012 um 14:42 Uhr


  • Fehlerprotokoll zeigt nichts über das Problem. Ich habe display_errors und error_reporting aktiviert. Kann immer noch nichts zu dem Problem finden.

    – carcargi

    30. August 2012 um 15:06 Uhr

1646954052 400 Wie kann ich Probleme mit exec debuggen
Kuf

schau mal /etc/php.ini dort unter:

; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.disable-functions
disable_functions =

Stellen Sie sicher, dass exec nicht wie folgt aufgeführt ist:

disable_functions=exec

Wenn ja, entfernen Sie es und starten Sie den Apache neu.

Zum einfachen Debuggen führe ich die PHP-Datei normalerweise gerne manuell aus (kann weitere Fehler anfordern, ohne sie in der Haupt-INI festzulegen). Fügen Sie dazu den Header hinzu:

#!/usr/bin/php
ini_set("display_errors", 1);
ini_set("track_errors", 1);
ini_set("html_errors", 1);
error_reporting(E_ALL);

am Anfang der Datei, geben Sie ihr Berechtigungen mit chmod +x myscript.php und führe es aus ./myscript.php. Dies ist besonders auf einem ausgelasteten Server, der viel in die Protokolldatei schreibt, sehr umsichtig.

BEARBEITEN

Klingt wie ein Berechtigungen Ausgabe. Erstellen Sie ein Bash-Skript, das etwas Einfaches tut echo "helo world" und versuchen, es auszuführen. Stellen Sie sicher, dass Sie Berechtigungen für die Datei haben und für den Ordner, der die Datei enthält. du könntest es einfach tun chmod 755 nur zum testen.

  • disable_functions ist leer in meinem php.iniich führe das Skript wie von Ihnen vorgeschlagen aus und die Konsole zeigt nichts an.

    – carcargi

    30. August 2012 um 15:09 Uhr

  • Vielen Dank, das hat den Trick getan, das Problem war, dass er irgendwie (da mein Client Zugriff auf den Server hat und er denkt, er sei ein Experte XD) die Berechtigungen der Apps kopiert und geändert hat. Ich habe sie zurück in den ursprünglichen Ordner verschoben und den Pfad neu konfiguriert, jetzt funktioniert alles, ich habe dies beim Testen der Berechtigungen der Anwendung gefunden. Danke.

    – carcargi

    30. August 2012 um 15:25 Uhr

  • @Necroside er hat die Berechtigungen von geändert whoami??

    – Jack

    30. August 2012 um 15:32 Uhr

  • Mmm, das ist eine gute Frage. Ich habe gerade einige Berechtigungen und das Pfadproblem gefunden und dies dem Server gemeldet, und sie haben dies in kürzester Zeit behoben. Ich werde fragen, ob das Ticket inzwischen geschlossen ist. Die Antwort, die ich vom Server erhielt, war, dass einer von uns (wir verwenden beide dasselbe Konto) den Pfad geändert und einige Anwendungen kopiert habe, also habe ich sie gebeten, sie dorthin zu verschieben und zurückzukopieren, wo sie hingehören, und ich habe einfach den Pfad geändert und geändert die Berechtigungen der Apps, die ich brauchte. Ich bin kein Linux/Unix-Experte.

    – carcargi

    30. August 2012 um 15:51 Uhr


  • Nein, whoami wurde nicht geändert, es wurde nur verschoben und ich weiß nicht, wie es funktioniert, aber es war in einem anderen Pfad, den PHP nicht finden konnte. Ich konnte es von der Konsole aus ausführen.

    – carcargi

    30. August 2012 um 21:32 Uhr

Wie kann ich Probleme mit exec debuggen
Mario

Noch ein paar Anmerkungen

  • Schließen Sie zum Debuggen immer Ihre Funktion exec/shell_exec ein var_dump().

  • error_reporting(-1); sollte eingeschaltet sein, wie es sein sollte display_errorsals letzten Ausweg sogar set_error_handler("var_dump"); – nur um zu sehen, ob PHP selbst nicht aufgerufen wurde execvp oder aber.

  • Verwenden 2>&1 (Verbinden Sie die Shells STDERR mit dem STDOUT-Stream), um zu sehen, warum ein Aufruf fehlschlägt.
    In einigen Fällen müssen Sie Ihren Befehl möglicherweise in einen zusätzlichen Shell-Aufruf einschließen:

    // capture STDERR stream via standard shell
    echo shell_exec("/bin/sh -c 'ffmpeg -opts 2>&1' ");
    

    Sonst die Protokolldateiumleitung wie von @Mike empfohlen, ist der empfehlenswerteste Ansatz.

  • Wechseln Sie zwischen den verschiedenen exec-Funktionen, um andernfalls Fehlermeldungen aufzudecken. Während sie meistens dasselbe tun, variieren die Ausgangsrückwege:

    1. exec() → Gibt die Ausgabe entweder als Funktionsergebnis zurück oder über das optionale $output Parameter.
      Bietet auch eine $return_var Parameter, der den Errno-/Exit-Code der ausgeführten Anwendung oder Shell enthält. Sie könnten Folgendes erhalten:

      • ENOENT (2) – Keine solche Datei
      • EIO (127) – E/A-Fehler: Datei nicht gefunden
      // run command, conjoined stderr, output + error number
      var_dump(exec("ffmpeg -h 2>&1", $output, $errno), $output, $errno));
      
    2. shell_exec() → ist das, was Sie hauptsächlich für Ausdrücke im Shell-Stil ausführen möchten.
      Stellen Sie sicher, dass Sie den Rückgabewert mit zB zuweisen / drucken var_dump(shell_exec("..."));

    3. `` Inline-Backticks → sind identisch mit shell_exec.

    4. system() → ist ähnlich wie exec, gibt aber die Ausgabe immer als Funktionsergebnis zurück (ausdrucken!). Ermöglicht zusätzlich das Erfassen des Ergebniscodes.

    5. passthru() → ist eine andere exec Alternative, sendet aber immer alle STDOUT-Ergebnisse an den Ausgabepuffer von PHP. Was es oft zum passendsten Exec-Wrapper macht.

    6. popen() oder besser proc_open() → ermöglicht die individuelle Erfassung von STDOUT und STDERR.

  • Die meisten Shell-Fehler landen in PHPs oder Apaches error.log wenn nicht umgeleitet. Überprüfen Sie Ihr Syslog- oder Apache-Protokoll, wenn nichts nützliche Fehlermeldungen liefert.

Die häufigsten Probleme

  • Wie von @Kuf erwähnt: für veraltete Webhosting-Pläne konnte man noch fündig werden safe_mode oder disable_functions aktiviert. Keine der PHP-Exec-Funktionen wird funktionieren. (Am besten einen besseren Anbieter finden, sonst “CGI” recherchieren – aber nicht Installieren Sie Ihren eigenen PHP-Interpreter, während Sie sich nicht auskennen.)

  • Ebenso kann AppArmor/SELinux/Firejail manchmal an Ort und Stelle sein. Diese schränken die Fähigkeit jeder Anwendung ein, neue Prozesse hervorzubringen.

  • Das beabsichtigte binär existiert nicht. So ziemlich kein Webhost hat Tools wie ffmpeg vorinstalliert. Sie können nicht einfach beliebige Shell-Befehle ohne Vorbereitung ausführen. Einige Dinge müssen installiert werden!

    // Check if `ffmpeg` is actually there:
    var_dump(shell_exec("which ffmpeg"));
    
  • Die PATH ist aus. Wenn Sie benutzerdefinierte Tools installiert haben, müssen Sie sicherstellen, dass sie erreichbar sind. Verwenden var_dump(shell_exec("ffmpeg -opts")) wird alle gängigen Pfade durchsuchen – oder wie Apache gesagt/eingeschränkt wurde (oft nur /bin:/usr/bin).

    Überprüfen Sie mit print_r($_SERVER); was Ihr PATH enthält und ob das das Tool abdeckt, das Sie ausführen wollten. Andernfalls müssen Sie möglicherweise die Servereinstellungen (/etc/apache2/envvars) anpassen oder vollständige Pfade verwenden:

    // run with absolute paths to binary
    var_dump(shell_exec("/bin/sh -c '/usr/local/bin/ffmpeg -opts 2>&1'"));
    

Dies untergräbt etwas das Shell-Konzept. Das halte ich persönlich nicht für wünschenswert. Aus Sicherheitsgründen ist es jedoch sinnvoll; darüber hinaus natürlich für die Verwendung einer benutzerdefinierten Installation.

  • Berechtigungen

    1. Um eine Binärdatei auf einem BSD/Linux-System auszuführen, muss sie “ausführbar” gemacht werden. Das ist was chmod a+x ffmpeg tut.

    2. Außerdem muss der Pfad zu solchen benutzerdefinierten Binärdateien für den lesbar sein Apache-Benutzerunter der Ihre PHP-Skripte ausgeführt werden.

    3. Modernere Setups verwenden den in PHP integrierten FPM-Modus (suexec+FastCGI), wobei Ihr Webhosting-Konto dem entspricht, mit dem PHP ausgeführt wird.

  • Testen Sie mit SSH. Es sollte selbstverständlich sein, aber bevor Sie Befehle über PHP ausführen, wäre es sehr sinnvoll, sie in einer echten Shell zu testen. Sonde mit zB ldd ffmpeg ob alle lib-Abhängigkeiten vorhanden sind und ob es ansonsten funktioniert.

  • Verwenden namei -m /Usr/local/bin/ffmpeg um den gesamten Pfad zu untersuchen, wenn Sie sich nicht sicher sind, woher Probleme mit der Zugriffsberechtigung kommen könnten.

  • Eingabewerte (GET, POST, FILE-Namen, Benutzerdaten), die als übergeben werden Befehlsargumente in exec Strings müssen mit maskiert werden escapeshellarg().

    $q = "escapeshellarg";
    var_dump(shell_exec("echo {$q($_GET['text'])} | wc"));
    

    Andernfalls erhalten Sie leicht Shell-Syntaxfehler; und wahrscheinlich später installierter Exploit-Code …

  • Achten Sie darauf, Backticks nicht mit einem der zu kombinieren *exec() Funktionen:

    $null = shell_exec(`wc file.txt`);
                       ↑           ↑
    

    Backticks würden den Befehl ausführen und Shell_exec mit der Ausgabe des bereits ausgeführten Befehls verlassen. Verwenden Sie normale Anführungszeichen zum Umschließen des Befehlsparameters.

  • Prüfen Sie auch in einer Shell-Session, wie das vorgesehene Programm mit einem anderen Account funktioniert:

    sudo -u www-data gpg -k
    

    Insbesondere für PHP-FPM-Setups testen Sie mit der entsprechenden Benutzer-ID. www-data/apache werden meistens nur von alten mod_php-Setups verwendet.

    Viele cmdline-Tools hängen von einer Konfiguration pro Benutzer ab. Dieser Test zeigt oft, was fehlt.

  • Sie können keine Ausgabe für im Hintergrund ausgeführte Prozesse erhalten, die mit gestartet wurden … & oder nohup …. In solchen Fällen müssen Sie unbedingt eine Protokolldateiumleitung verwenden exec("cmd > log.txt 2>&1 &");

Unter Windows

  • CMD-Aufrufe funktionieren oft nicht gut mit STDERR-Streams.

  • Probieren Sie auf jeden Fall ein Powershell-Skript aus, um andere CLI-Apps auszuführen, oder verwenden Sie eine Befehlszeile wie:

     system("powershell -Command 'pandoc 2>&1'");
    
  • Verwenden Sie vollständige Pfade und bevorzugen Sie immer Schrägstriche ("C:/Program Files/Whatevs/run.exe" mit zusätzlichen Anführungszeichen, wenn Pfade Leerzeichen enthalten).

    Schrägstriche funktionieren auch unter Windows, seit sie in MS-DOS 2.0 eingeführt wurden

  • Finden Sie heraus, unter welchem ​​Dienst und SAM-Konto IIS/Apache und PHP ausgeführt werden. Stellen Sie sicher, dass es über Ausführungsberechtigungen verfügt.

  • Sie können normalerweise keine GUI-Apps ausführen. (Eine typische Problemumgehung sind die Taskplaner- oder WMI-Aufrufe.)

PHP → Python, Perl

Wenn Sie einen anderen Skriptinterpreter von PHP aus aufrufen, verwenden Sie im Falle von Fehlern alle verfügbaren Debugging-Mittel:

passthru("PYTHONDEBUG=2 python -vvv script.py 2>&1");
passthru("perl -w script.pl 2>&1");
passthru("ruby -wT1 script.rb 2>&1");

Oder vielleicht sogar mit irgendeiner Syntax ausführen -c Option zuerst prüfen.

  • Tolle Antwort, ich bin überrascht, dass es nicht mehr Upvotes gibt. Die akzeptierte Lösung ist nicht so nützlich wie diese.

    – kevinkl3

    26. Juni 2018 um 0:07 Uhr


Da Sie aus dem PHP-Kontext in die native Shell wechseln, werden Sie viele Probleme beim Debuggen haben.

Das Beste und Narrensicherste, das ich in der Vergangenheit verwendet habe, war, die Ausgabe des Skripts in eine Protokolldatei zu schreiben und sie während der PHP-Ausführung zu verfolgen.

<?php
shell_exec("filename > ~/debug.log 2>&1");

Dann in einer separaten Shell:

tail -200f ~/debug.log

Wenn Sie Ihr PHP-Skript ausführen, werden Ihre Fehler und die Ausgabe Ihres Shell-Aufrufs in Ihrer angezeigt debug.log Datei.

Sie können die Ausgaben und den Rückgabecode des abrufen Exekutive Befehle, diese könnten Informationen enthalten, die das Problem erklären würden…

exec('my command', $output, $return);

989240cookie-checkWie kann ich Probleme mit exec() debuggen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy