2014-04-27 7 views
7

Desidero riavviare il computer eseguendo un comando in linux utilizzando QProcess. Ho hardcoded la mia password di root nella mia applicazione.Come eseguire comandi complessi di linux in Qt?

Quando si esegue il seguente in un terminale funziona perfetto:

echo myPass | sudo -S shutdown -r now 

Quando metto il comando in uno script shell e chiamo tramite QProcess è anche successo:

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

Ma non posso eseguirlo passando direttamente a QProcess:

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

Sarà appena stampato myPass | sudo -S shutdown -r now

Come è possibile eseguire comandi relativamente complessi direttamente utilizzando QProcess. (Non inserire uno script di shell).

risposta

9

I metodi chiave esistenti per questo scopo stabilito in QProcess:

void QProcess::setProcessChannelMode(ProcessChannelMode mode)

e

void QProcess::setStandardOutputProcess(QProcess * destination)

Pertanto, il fo Codice llowing frammento sarebbe l'equivalenza di command1 | command2 senza limitare a voi stessi di un interprete o di un altro:

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; 
} 

potrebbe cadere la parte sudo -S perché si potrebbe eseguire questo piccolo programma come root, così come l'impostazione dei diritti. È anche possibile impostare setuid o setcap per il programma di spegnimento.

Quello che solitamente facciamo quando si costruiscono sistemi Linux commerciali è di avere un'applicazione minima che può ottenere setuid o setcap per l'attività che sta tentando di fare, e quindi la chiamiamo esplicitamente con system(3) o QProcess su Linux. In sostanza,

Vorrei scrivere che piccola applicazione per evitare di dare pieno accesso root per l'intera applicazione, in modo da limitare il diritto di accesso da un uso dannoso come segue:

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

Questo funziona bene e mi piace perché è più generale e più in un modo Qt. Non so a cosa serve questo: process2.setProcessChannelMode (QProcess :: ForwardedChannels); – Nejat

+0

@Nejat: sì, potrebbe funzionare senza, ma l'ultima volta ho avuto problemi quando non l'ho avuta. Lo scopo è di reindirizzare l'output del processo secondario al processo principale, quindi, sì, potrebbe non essere necessario per il tuo caso. – lpapp

1

È necessario mettere il comando in uno script di shell ed eseguire sh o bash con QProcess con il vostro script di shell come argomento, perché il comando contiene |, che deve essere interpretato da sh o bash.

Tuttavia, è solo una mia opinione, ma: non penso che sia una buona soluzione per fare ciò che stai facendo, cioè includere la tua password di root in un eseguibile.

+0

Questo non è raccomandato in quanto limita la disponibilità all'interprete dato – lpapp

+0

L'ho già provato con successo se hai letto la domanda. – Nejat

+0

@LaszloPapp: conosci un sistema Linux senza/bin/sh? La domanda riguardava Linux, non tutti i sistemi operativi. Se il comando fosse più complesso, con più pipe/redirector, cosa fai? 10 QProcess? È anche più flessibile dedicare il comando a uno script di shell: se si desidera modificare il comando, non è necessario compilare nuovamente il file eseguibile. – AntiClimacus

2

Innanzitutto, è possibile configurare sudo per evitare di chiederti la password. Per esempio con l'essere membro del gruppo sudo e avere la linea

%sudo ALL=NOPASSWD: ALL 

nel file /etc/sudoers. Ovviamente non chiedere la password riduce la sicurezza del tuo sistema.

per rispondere alla tua domanda circa Qt, ricordate che bash(1), come tutti i Posix conchiglie, quindi /bin/sh, accettare l'argomento -c con una stringa (in realtà system(3) si biforcano un /bin/sh -c). Quindi, solo eseguire

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

Come AntiClimacus answered, mettendo la password di root all'interno di un eseguibile è una cattiva idea.

+0

È un'idea non ottimale, perché Qt ha un'API dedicata per questo che non limita l'utente a un interprete. – lpapp

+0

Inoltre, sembra che l'OP abbia già provato questo, e ha anche chiesto 'Come è possibile eseguire comandi relativamente complessi direttamente usando QProcess. (Non inserire uno script di shell) .' – lpapp