У меня есть скрипт 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
}