Не могу запустить bash-скрипт в QProcess
Доброго времени суток.
Пишу программу в Qt.
Мне требуется сканировать сегменты сети на наличие активных устройств.
Использую для этого nmap. Дабы не парсить вывод nmap в самом Qt, использую дополнительно фильтры grep и awk.
Собственно, список активных машин в сегменте
proc = new QProcess();
_proc->setProgram("/bin/bash");
_proc->setArguments(QStringList() << "-c" << "nmap -sP " + _address + ".0/24 | grep -E -o \"[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$\" | awk -F \".\" '{ if(($4 > 0) && ($4 < 255)) print $0;}'");
Ну, это как бы для примера.
Сканировать придётся много и по таймеру. Может, неочень правильное решение, так как каждый nmap жрёт какое-то количество памяти, нужно выделить достаточно на виртуалке. Но, неважно, пока ничего мудрее не придумал.
Сканировать так же нужно будет и порты, так, что использование чисто дефолтного ping не имеет смысла.
Собственно, в чём проблема. Когда создаю процесс в QProcess, то родительским процессом становится /bin/bash, а при его убиении nmap, awk, grep висят в процессах пока nmap не завершит сканирование. А если я закрыл программу, какой смысл висеть десятку nmap?
Долго лазил по инету и ничего мудрее не придумал, как написать ещё один скрипт для убиения родителя и его потомков.
Собственно, сам виновник данной темы:
#!/bin/bash
PID=$1
METKA=(`ps -A | grep -v PID | awk 'BEGIN{C="NO";}{if($1=='$PID') C="YES";}END{print C;}'`)
if [[ "$METKA" == "YES" ]]
then
for z in `ps -ejH | grep -E "(bash)|(nmap)|(grep)|(awk)" | awk 'BEGIN{N=1;}{PID[N]=$1;name[N]=$6;N++;}END{for(i=1;i<N;i++) {if((PID[i]=='$PID') && ((i+3)<N)) {if((name[i]=="bash")&&(name[i+1]=="nmap")&&(name[i+2]=="grep")&&(name[i+3]=="awk")){print PID[i],PID[i+1],PID[i+2],PID[i+3]; break;} }} }'`
do
echo "${z}"
kill ${z}
done
fi
Я не скриптолог, но что получилось, то получилось.
Если я вызываю этот скрипт из терминала, то он штатно выполняет свою работу.
А вот, Qt ругается по-страшному или молчит, но убивать nmapы не собирается. При таком запуске скрипта в деструкторе
QProcess::startDetached("/bin/bash",QStringList() << "-c" << "./script.sh" << QString::number(PID));
выдаёт:
QProcess: Destroyed while process ("/bin/bash") is still running.
QProcess: Destroyed while process ("/bin/bash") is still running.
awk: awk: PID= "192.168.55" 11067
cmd. line:1: BEGIN{C="NO";}{if($1==) C="YES";}END{print C;}
awk: cmd. line:1: ^ syntax error
cmd. line:1: BEGIN{C="NO";}{if($1==) C="YES";}END{print C;}
awk: cmd. line:1: ^ syntax error
QProcess: Destroyed while process ("/bin/bash") is still running.
awk: cmd. line:1: BEGIN{C="NO";}{if($1==) C="YES";}END{print C;}
awk: cmd. line:1: ^ syntax error
QProcess: Destroyed while process ("/bin/bash") is still running.
awk: cmd. line:1: BEGIN{C="NO";}{if($1==) C="YES";}END{print C;}
awk: cmd. line:1: ^ syntax error
grep: ошибка записи: Обрыв канала
grep: ошибка записи: Обрыв канала
grep: ошибка записи: Обрыв канала
grep: ошибка записи: Обрыв канала
При таком:
QProcess::startDetached("/bin/bash",QStringList() << "-c" << "./script.sh " + QString::number(PID));
QProcess: Destroyed while process ("/bin/bash") is still running.
QProcess: Destroyed while process ("/bin/bash") is still running.
QProcess: Destroyed while process ("/bin/bash") is still running.
QProcess: Destroyed while process ("/bin/bash") is still running.
Собственно, на это «is still running» можно не обращать внимания, так как я перед закрытием программы временно закомментил закрытие процесса.
Суть в том, что скрипт из терминала работает:
pavel@astra1:~/newnetmonitor/build-newNetMonitor-Desktop_Qt_5_10_0_GCC_64bit-Debug$ ./script.sh 11704
11704
11705
11706
./script.sh: строка 15: kill: (11706) - Нет такого процесса
11707
./script.sh: строка 15: kill: (11707) - Нет такого процесса
а из Qt нет. Awk и grep по идее можно не удялять, так как они сами закрываются при убиении nmap, что и видно в сообщении.
В чём может быть причина и как грамотнее вызывать скрипт так:
QProcess::startDetached("/bin/bash",QStringList() << "-c" << "./script.sh" << QString::number(PID));
или так:
QProcess::startDetached("/bin/bash",QStringList() << "-c" << "./script.sh " + QString::number(PID));
Может я неправильно внешние аргументы в awk подаю «if($1=='$PID')». Не знаю…
В конечном итоге нужно убить родительский процесс и всех его потомков по PID и хотелось бы этот скрипт одной строкой записать, чтобы можно было не из файла, а из Qt вызвать, как я это делаю с nmap.