У меня есть сценарий bash, который обрабатывает данные за несколько лет, поэтому на выполнение сценария может уйти неделя. Чтобы ускорить процесс, я использую многопоточность, запуская несколько экземпляров параллельно (каждый экземпляр = 1 день данных). Каждый экземпляр занимает 1 ЦП, поэтому я могу запускать столько экземпляров, сколько доступно ЦП. Поскольку я запускаю процесс на мощном сервере, которым я делюсь с другими, в какой-то момент у меня может быть больше или меньше доступных процессоров. Мой текущий сценарий:
#!/bin/bash
function waitpid {
#Gather the gLABs PID background processes (Maximum processes in
#background as number of CPUs)
NUMPIDS=`jobs -p|awk 'END {print NR}'`
#A while is set because there seems to be a bug in bash that makes
#sometimes the "wait -n" command
#exit even if none of provided PIDs have finished. If this happens,
#the while loops forces the
#script to wait until one of the processes is truly finished
while [ ${NUMPIDS} -ge ${NUMCPUS} ]
do
#Wait for gLAB processes to finish
PIDS="`jobs -p|awk -v ORS=" " '{print}'`"
wait -n ${PIDS} >/dev/null 2>/dev/null
NUMPIDS=`jobs -p|awk 'END {print NR}'`
done
}
NUMPCUS=10
for(...) #Loop for each day
do
day=... #Set current day variable
#Command to execute, put in background
gLAB_linux -input ${day}folder/${day}.input -output ${day)outfolder/${day}.output &
#Wait for any process to finish if NUMCPUS number of processes are running in background
waitpid
done
Поэтому мой вопрос: если этот скрипт запущен, могу ли я каким-либо образом изменить переменную NUMCPUS на любое значение (например, NUMCPUS=23) без остановки скрипта? Если возможно, я бы предпочел метод, который не требует чтения или записи в файл (мне нравится уменьшать количество временных файлов до 0, если это возможно). Я не возражаю, если это «хакерский» процесс, такой как метод, описанный в этот ответ. На самом деле, я пробовал в gdb те же команды, что и в этом ответе, но это не сработало, у меня были следующие ошибки в gdb (а также произошел сбой процесса):
(gdb) attach 23865
(gdb) call bind_variable("NUMCPUS",11,0)
'bind_variable' has unknown return type; cast the call to its declared return type
(gdb) call (int)bind_variable("NUMCPUS",11,0)
Program received signal SIGSEGV, Segmentation fault
EDIT1: Некоторые комментарии к сценарию:
- gLAB_linux — это программа обработки с одним ядром, которая не знает о переменной NUMCPUS.
- Каждое выполнение gLAB_linux занимает около 5 часов, поэтому скрипт bash большую часть времени спит внутри файла
wait -n
. - NUMCPUS должна быть локальной переменной для скрипта, так как параллельно может выполняться другой скрипт, подобный этому (изменение только параметров, заданных для gLAB_linux). Поэтому NUMCPUS не может быть переменной среды.
- Единственный процесс, обращающийся к NUMCPUS, — это сценарий bash.
EDIT2: после ответа @Kamil я добавляю свое предложение по чтению из файла количества процессоров.
function waitpid {
#Look if there is a file with new number of CPUs
if [ -s "/tmp/numCPUs_$$.txt" ]
then
TMPVAR=$(awk '$1>0 {print "%d",$1} {exit}' "/tmp/numCPUs_$$.txt")
if [ -n "${TMPVAR}" ]
then
NUMCPUS=${TMPVAR}
echo "NUMCPUS=${TMPVAR}"
fi
rm -f "/tmp/numCPUs_$$.txt"
fi
#Gather the gLABs PID background processes (Maximum processes in
#background as number of CPUs)
NUMPIDS=`jobs -p|awk 'END {print NR}'`
#A while is set because there seems to be a bug in bash that makes
#sometimes the "wait -n" command
#exit even if none of provided PIDs have finished. If this happens,
#the while loops forces the
#script to wait until one of the processes is truly finished
while [ ${NUMPIDS} -ge ${NUMCPUS} ]
do
#Wait for gLAB processes to finish
PIDS="`jobs -p|awk -v ORS=" " '{print}'`"
wait -n ${PIDS} >/dev/null 2>/dev/null
NUMPIDS=`jobs -p|awk 'END {print NR}'`
done
}
--limit
в GNU parallel. - person choroba   schedule 22.11.2018parallel
может читать строки cmd со стандартного ввода. - person georgexsh   schedule 22.11.2018wait -n
:wait -n
ожидает завершения следующего фонового задания; следующий как следующий из всех фоновых заданий текущего сеанса. PID, указанные после-n
, игнорируются. Вы можете проверить это с помощьюsleep 1 & sleep 9 & wait -n $!
.$!
— это PIDsleep 9
, ноwait
будет ждать толькоsleep 1
. - person Socowi   schedule 22.11.2018