Убийство скрипта bash не убивает дочерние процессы
Я написал тестовый скрипт, который запускает другой скрипт, чтобы запустить сервер для тестирования. Когда испытания завершены SIGKILL
сообщение отправляется процессу сервера, однако при повторном запуске тестового сценария сервер выдает EADDRINUSE
ошибка (я нахожусь в среде node.js), которая означает, что порт, к которому пытается подключиться сервер, в настоящее время используется. Процесс, который мы пытались убить SIGKILL
все еще работает. Я не верю, что это проблема конкретного узла, а скорее отсутствие у меня понимания, как работают процессы bash.
Вот некоторые особенности, это мой стартовый скрипт scripts/start-node.sh
:
#!/bin/bash
node_modules/.bin/babel-node --stage 0 index.js
Это мой узел сервера называется index.js
(Я не был автором process
слушатели событий):
Http.createServer(…).listen(PORT, () => console.log(`Server listening on ${PORT}`))
И стартовый скрипт контролируется с помощью узла child_process
модуль:
var child = child_process.spawn('scripts/start-node.sh')
// Later…
child.kill('SIGKILL')
3 ответа
Чтобы убить дочерний процесс и всех его детей, вы можете использовать process.kill
с отрицательным pid
(убить группу процессов)
var child = child_process.spawn('scripts/start-node.sh', {detached: true})
// Later…
process.kill(-child.pid, 'SIGKILL');
Смотрите подробности на child_process
документация для options.detached
В не-Windows, если установлена опция отсоединения, дочерний процесс будет сделан лидером новой группы процессов и сеанса.
Ссылка здесь часть man 2 kill
для некоторых деталей:
Если pid меньше -1, то sig отправляется каждому процессу в группе процессов с идентификатором -pid.
Другой вариант может использовать trap
в вашем сценарии оболочки, чтобы перехватить сигнал и убить всех детей и используя child.kill('SIGTERM')
от node
(как SIGKILL
не будет перехвачен trap
)
#!/bin/bash
trap 'kill $(jobs -p)' EXIT
node_modules/.bin/babel-node --stage 0 index.js
Просто:
#!/bin/bash
if pgrep -x "node" > /dev/null
then
mv -f /usr/local/bin/node /usr/local/bin/node.1
killall node
mv -f /usr/local/bin/node.1 /usr/local/bin/node
which node
else
echo "process node not exists"
fi
узел создает дочерний процесс каждый раз, когда мы его убиваем. Поэтому невозможно убить процесс с помощью команд kill, pkill или killall. Таким образом, мы удаляем команду узла, чтобы вызвать сбой процесса разветвления, а затем убиваем процесс. Наконец, мы восстанавливаем команду узла.
Иметь обработчик для сигналов процесса на вашем сервере
server.js
var http = require('http');
function handleRequest(request, response){
response.end("Hello");
}
var server = http.createServer(handleRequest);
server.listen(3000, function(){console.log("listening...")});
process.title="testserver"
process.on('SIGQUIT', function() {
server.close()
});
startup.sh
#!/bin/bash
node server.js & echo "started"
а затем есть "shutdown.sh".
shutdown.sh
#!/bin/bash
pkill -QUIT testserver & echo "stoped"
Он убьет все процессы с таким именем, если вы создадите многократные процессы в вашем файле start-node.sh. Таким образом, вы можете иметь некоторый код очистки при завершении работы, например, закрытие всех соединений и т. Д.
и в своем тесте вы можете сделать
var exec = require('child_process').exec;
exec("./start.sh")
// later...
exec("./stop.sh")
У вас есть выход 0 в вашем скрипте?
Пример:
#!/bin/bash
ifconfig
exit 0