Назад | Перейти на главную страницу

Борьба с sed, чтобы найти и переформатировать дату входа в систему (или, как убить простаивающие процессы mosh-сервера)

У меня есть старый метод уничтожения простаивающих процессов mosh-сервера, который не работает на моем новом VPS.

Вот старый метод, который я запускаю в crontab root для очистки mosh-процессов, которые простаивали более 10 дней:

for tty in `w -sf | grep -P '\d\ddays mosh-server' | cut -c 10-15`; do kill -9 `ps -o pid= -t $tty`; done

Проблема в том, что на новом VPS эти процессы не имеют TTY, поэтому я не могу сопоставить TTY и таким образом уничтожить mosh. Вот что у меня есть (кстати, новый VPS работает под управлением ядра 3.2 на Debian wheezy, старый был предыдущей версией Debian).

for loginday in `w | grep -P '\d\ddays.* mosh-server' | cut -c 34-40 | sed 's/^\([0-9]*\)\([a-zA-Z]*\).*$/\2 \1/'`; do echo $loginday; done

Я пытаюсь получить день входа в систему от 'w' и позже сопоставить его с информацией из 'ps':

ps -C mosh-server -o bsdstart

Таким образом, я мог сопоставить любые неактивные сеансы mosh-сервера, начатые в тот же день, что и вход в систему (что, вероятно, составляет 99,9% из них в дикой природе), и убить их ТАКИМ образом, используя 'ps' для получения pid.

Однако 'w' выводит день входа следующим образом:

03Oct13

Который я сократил до просто «03Oct».

И ps выводит так:

Oct 3

Вы можете видеть в приведенной выше команде sed, которая является частью, которая не работает, я пытаюсь взять «03Oct» и вывести «Oct 03» (я разберусь с нулями, когда это заработает) и Я не могу заставить себя работать внутри цикла for когда кажется, что он работает, когда я тестирую его с помощью 'echo':

echo 03Oct | sed 's/\([0-9]*\)\([a-zA-Z]*\).*/\2 \1/'

Что меняет команду sed, когда я вставляю ее в цикл for?

Еще лучше, есть ли лучший или менее хакерский способ сделать это? Учитывая, что отдельные процессы бездействующего mosh-сервера не имеют TTY в Linux 3.2, которые я могу легко сопоставить? Редактировать: Кроме того, в системах с установленным libutempter mosh-сервер запишет информацию в utmp это, как я подозреваю, было бы полезно, но я не знаю, как это сделать.

Чтобы сделать что-то более точное, чем анализ дат, вы можете посмотреть файловую систему / proc. Что-то вроде этого работает у меня на redhat:

⚡ for pid in $(pgrep mosh-server -u $USER); do if [[ $(stat -c %Y /proc/$pid) -lt $(( $(date +%s) - 36000 )) ]]; then echo "$pid is probably stale";fi;  done
27831 is probably stale                                                                                                                                      
38041 is probably stale                                                                                                                                      
38669 is probably stale                                                                                                                                      

⚡ ps fux | grep mosh                                                                                                                                         
1524      2444  0.4  0.0 160352  4752 ?        S    08:27   0:00 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod                          
1524     27831  0.0  0.0 161648  6288 ?        S    Apr05   0:02 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod                          
1524     38041  0.0  0.0 159696  4332 ?        S    Apr04   0:03 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod                          
1524     38669  0.0  0.0 161276  5920 ?        S    Apr04   0:37 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod 

Измените эхо на kill, а 36000 - на то, что вы хотите, чтобы ваш таймаут в секундах был. Если вы хотите сделать это для всех пользователей, отбросьте -u $ USER и запустите его как root.

Ваш echo test отличается от вашего теста цикла двумя важными способами:

  • Вокруг даты нет пробела
  • в регулярном выражении отсутствуют якоря

Одна из причин, по которой ваш тест цикла не работает, заключается в том, что вы не учитываете пробелы. Другая причина в том, что вы используете * квантификатор, который означает «ноль или более» и имеет эффект, что вам нужны цифры, но не совсем. Чтобы исправить это, вы можете использовать + квантификатор, который означает «один или несколько». Мы будем использовать это для альфа-символов. Однако, поскольку вы хотите удалить ведущий ноль, мы можем немного изменить направление цифр.

Поскольку GNU sed поддерживает расширенные регулярные выражения, мы можем исключить экранирование всех этих специальных символов, а также тех, которые я добавил. Обратите внимание, однако, что -r вариант не переносной. Кроме того, я заменяю именованный класс символов на алфавитные символы, чтобы сделать регулярное выражение более читабельным и сделать его совместимым с языками с разными наборами символов.

sed -r 's/^ *((0)|([1-9]))([0-9])([[:alpha:]]+).*$/\5 \3\4/'

Ведущий ноль фиксируется в группе 2 и отбрасывается. Группа 1 - это первая цифра двузначного числа. Группа 3 пуста, если группа 2 содержит ноль (из-за чередования, созданного с помощью символа вертикальной черты).

Так далеко как utmp идет, делает last mosh-server вывести что-нибудь полезное для вас (с установленной libutempter)?

Пожалуйста, также смотрите Управление процессом чтобы узнать, найдете ли вы что-нибудь полезное