2014-04-27 5 views
7

Ich möchte den Computer neu starten, indem Sie einen Befehl in Linux mit QProcess ausführen. Ich habe mein Root-Passwort in meiner Anwendung fest programmiert.Wie führe ich komplexe Linux Befehle in Qt aus?

Wenn ich die folgenden in einem Terminal ausführen es funktioniert perfekt:

echo myPass | sudo -S shutdown -r now 

Wenn ich in ein Shell-Skript den Befehl setzen und rufen es über QProcess es ist auch erfolgreich:

QProcess process; 
process.startDetached("/bin/sh", QStringList()<< "myScript.sh"); 

Aber ich kann es nicht direkt vorbei an QProcess laufen:

process.startDetached("echo myPass | sudo -S shutdown -r now "); 

Es wird nur gedruckt myPass | sudo -S shutdown -r now

Wie ist es möglich, solche relativ komplexe Befehle direkt mit QProcess auszuführen. (Kein Shell-Skript einfügen).

Antwort

9

Die wichtigsten Methoden, die in QProcess für diesen Zweck eingerichtet sind:

void QProcess::setProcessChannelMode(ProcessChannelMode mode)

und

void QProcess::setStandardOutputProcess(QProcess * destination)

Daher ist die fo llowing Code-Schnipsel wäre die Äquivalenz von command1 | command2, ohne sich auf einen Dolmetscher zu begrenzen oder eine andere:

QProcess process1 
QProcess process2; 

process1.setStandardOutputProcess(&process2); 

process1.start("echo myPass"); 
process2.start("sudo -S shutdown -r now"); 
process2.setProcessChannelMode(QProcess::ForwardedChannels); 

// Wait for it to start 
if(!process1.waitForStarted()) 
    return 0; 

bool retval = false; 
QByteArray buffer; 
// To be fair: you only need to wait here for a bit with shutdown, 
// but I will still leave the rest here for a generic solution 
while ((retval = process2.waitForFinished())); 
    buffer.append(process2.readAll()); 

if (!retval) { 
    qDebug() << "Process 2 error:" << process2.errorString(); 
    return 1; 
} 

Sie könnten den sudo -S Teil fallen, weil Sie dieses kleine Programm als root ausführen können, sowie die Rechte einrichten. Sie könnten setuid oder setcap für das Shutdown-Programm festlegen.

Was wir normalerweise tun, wenn kommerzielle Linux-Systeme gebaut werden, ist eine minimale Anwendung, die setuid oder setcap für die Aktivität erhalten kann, die es versucht, und dann nennen wir das explizit mit system(3) oder QProcess unter Linux. Grundsätzlich

Ich würde diese kleine Anwendung schreiben zu vermeiden vollen Root-Zugriff auf die gesamte Anwendung zu geben, so das Zugriffsrecht gegen schädliche Verwendung zu beschränken, wie folgt:

sudo chmod u+s /path/to/my/application 
+0

Das funktioniert gut und ich mag es, weil es allgemeiner und mehr in Qt-Art ist. Ich weiß nicht, wofür das ist: process2.setProcessChannelMode (QProcess :: ForwardedChannels); – Nejat

+0

@Nejat: Ja, es könnte ohne das funktionieren, aber beim letzten Mal hatte ich Probleme, wenn ich das nicht hatte. Der Zweck ist es, die Ausgabe des Kindprozesses an den Hauptprozess umzuleiten, also, ja, das kann für Ihren Fall unnötig sein. – lpapp

1

Sie müssen den Befehl in einem Shell-Skript setzen und sh oder bash mit QProcess mit Ihrem Shell-Skript als Argument ausführen, weil Ihr Befehl | enthält, die muss von sh oder bash interpretiert werden.

Allerdings ist es nur meine Meinung, aber: Ich denke nicht, dass es eine gute Lösung ist, um das zu tun, was Sie tun, d. H. Ihr Root-Passwort in einer ausführbaren Datei enthalten.

+0

Dies ist nicht empfehlenswert, da sie die Verfügbarkeit beschränkt zu dem gegebenen Dolmetscher. – lpapp

+0

Ich habe das schon erfolgreich versucht, wenn Sie die Frage gelesen haben. – Nejat

+0

@LaszloPapp: Kennst du ein Linux-System ohne/bin/sh? Die Frage lautete Linux, nicht alle Betriebssysteme. Wenn der Befehl mit mehreren Pipes/Redirectors komplexer ist, was tun Sie? 10 QProzess? Es ist auch flexibler, den Befehl in einem Shell-Skript zu speichern: Wenn Sie den Befehl ändern möchten, müssen Sie Ihre ausführbare Datei nicht erneut kompilieren. – AntiClimacus

2

Zuerst können Sie sudo konfigurieren, damit Sie nicht nach dem Passwort fragen müssen. Zum Beispiel durch Mitglied der sudo Gruppe zu sein und die Linie

%sudo ALL=NOPASSWD: ALL 

in Ihrer /etc/sudoers Datei hat. Natürlich stellt die Frage nach dem Passwort die Sicherheit Ihres Systems nicht herab.

Ihre Frage zu Qt zu beantworten, denken Sie daran, dass bash(1), wie alle Posix Muscheln, daher /bin/sh, mit einer Schnur, die -c Argument akzeptieren (tatsächlich ist system(3) ein /bin/sh -c Forking). So führen Sie einfach

process.startDetached("/bin/sh", QStringList()<< "-c" 
         << "echo myPass | sudo -S shutdown -r now"); 

Als AntiClimacus answered, Puting Ihr Root-Passwort innerhalb einer ausführbaren eine schlechte Idee ist.

+0

Es ist eine suboptimale Idee, weil Qt hierfür dedizierte API hat, die Sie nicht auf einen Interpreter beschränkt. – lpapp

+0

Es scheint auch, dass das OP dies bereits versucht hat, und fragte auch: Wie ist es möglich, solche relativ komplexen Befehle direkt mit QProcess auszuführen. (Nicht in ein Shell-Skript einfügen.) – lpapp