Я ищу способ просмотреть временную метку задания в CUPS. Я искал на страницах man и не могу найти.
Долгосрочная цель — иметь скрипт, который анализирует время из jobID и автоматически удаляет любое задание, которое старше определенного возраста, чтобы избежать перегрузки сервера. На моем сервере CUPS более 2000 очередей печати.
решение1
Я нашел следующие 2 вопроса на сайте U&L, которые, как мне кажется, дают подсказки о возможном способе сделать это. Эти 2 вопроса:
- Просмотр всех заданий печати пользователя из командной строки
- Как просмотреть историю заданий принтера CUPS?
Кажется, подразумевается, что вы можете использовать, lpstat
чтобы получить то, что вы хотите. Я заметил, что я могу запустить эту команду:
$ sudo lpstat -W completed
mfc-8480dn-1652 root 1024 Tue 28 Jan 2014 01:19:34 AM EST
И этот:
$ sudo lpstat -W completed -u saml | head -2
mfc-8480dn-1524 saml 23552 Thu 28 Nov 2013 10:45:44 AM EST
mfc-8480dn-1526 saml 699392 Sat 30 Nov 2013 10:34:34 AM EST
Но -u all
мне это ничего не дало.
$ sudo lpstat -W completed -u all | head -2
$
Любопытно, что я мог бы сделать это:
$ sudo lpstat -W completed -u saml,root | head -3
mfc-8480dn-1524 saml 23552 Thu 28 Nov 2013 10:45:44 AM EST
mfc-8480dn-1526 saml 699392 Sat 30 Nov 2013 10:34:34 AM EST
mfc-8480dn-1652 root 1024 Tue 28 Jan 2014 01:19:34 AM EST
Поэтому один из хакерских способов сделать это — формализовать список пользователей в вашей системе, а затем добавить его в качестве подкоманды к -u
аргументу, например так:
$ sudo lpstat -W completed -u $(getent passwd | \
awk -F: '{print $1}' | paste -sd ',')
Чтобы показать, что здесь отображаются все пользователи локально, вы можете получить уникальный список ваших пользователей следующим образом:
$ sudo lpstat -W completed -u $(getent passwd | \
awk -F: '{print $1}' | paste -sd ',') | awk '{print $2}' | sort -u
ethan
root
sam
tammy
Проблемы?
Одна из проблем заключается в том, что если у пользователя, печатающего в CUPS, нет локальной учетной записи, то он не будет отображаться.
Но если у вас есть каталог, содержащий файлы управления LPD, то обычно это , you'll notice a bunch of control files in there. These files are kept as a result of the
настройка MaxJobs в /var/spool/cups, которая по умолчанию равна 500, если не задана.
$ sudo ls -l /var/spool/cups/ | wc -l
502
Еще один источник имен пользователей?
Если вы посмотрите эти файлы, то заметите, что они содержат имена пользователей, а не только имена учетных записей, присутствующих в системе.
$ strings /var/spool/cups/* | grep -A 1 job-originating-user-name | head -5
job-originating-user-name
tammyB
--
job-originating-user-name
tammyB
Таким образом, мы можем выбрать все записи, содержащие имя пользователя, за которым следует буква B.
$ sudo strings /var/spool/cups/* | grep -A 1 job-originating-user-name | \
grep -oP '.*(?=B)' | sort -u
ethan
guest-AO22e7
root
sam
saml
slm
tammy
Затем этот список можно адаптировать таким же образом, как мы изначально использовали для получения списка пользователей из getent passwd
, например так:
$ sudo lpstat -W completed -u $(strings /var/spool/cups/* | \
grep -A 1 job-originating-user-name | \
grep -oP '.*(?=B)' |sort -u | paste -sd ',')
mfc-8480dn-1525 tammy 545792 Thu 28 Nov 2013 01:36:59 PM EST
mfc-8480dn-1526 saml 699392 Sat 30 Nov 2013 10:34:34 AM EST
mfc-8480dn-1652 root 1024 Tue 28 Jan 2014 01:19:34 AM EST
mfc-8480dn-1672 saml 1024 Sun 09 Feb 2014 01:56:26 PM EST
Рекомендации
решение2
У меня есть другой, возможно, более простой подход к очистке старых заданий печати. Вместо того, чтобы искать способ конвертировать сокращенные временные метки в заданиях печати, проще использовать команду find для удаления старых заданий печати, соответствующих определенным критериям. Например, если вы хотите найти задания печати старше 4 дней:
find /var/spool/cups -name "*-001" -mtime +4
Все активные задания печати в cups имеют файлы /var/spool/cups
с расширением -001
. После этого вам останется только использовать ваш любимый инструмент для работы со строками, чтобы извлечь из вывода фактический номер задания печати.
решение3
На самом деле, полностью игнорируйте все это, и вообще не пытайтесь получить дату из списка заданий. Вам не нужно,если только вам не нужна точная временная метка задания печати (и даже в этом случае из выходных данных или руководства lpstat не сразу становится ясно, относится ли указанная дата и время к моменту отправки задания или к моменту его завершения).
Вам вообще не нужно этого делать, поскольку вы можете просто сгенерировать метку даты «сейчас» в тот момент, когда обнаружите свою работу в списке «завершенных» работ.
._. printJob=$(lp somefile | awk '{print $4}')
._. printJobCompleted=$(lpstat -W "completed" | grep $printJob )
._. printedDatestamp=$(date +%s)
Хотя, конечно, вы не можете сказать, что работа завершена, пока она не будет выполнена. Так что вы можете зациклиться и спать, пока не обнаружите, что она выполнена.
Если вам нужна дата, которая стоит в очереди, возможно, стоит сделать что-то вроде этого:
При отправке инструкции на печать запишите идентификатор задания на печать:
._. printJob=$(lp somefile | awk '{print $4}')
._. echo $printJob
Kyocera-ECOSYS-P5021cdw-564
(Необходимо проанализировать вывод lp через awk, поскольку, похоже, у lp нет возможности просто вернуть задание печати):
._. lp somefile
request id is Kyocera-ECOSYS-P5021cdw-568 (1 file(s))
( awk '{print $4}'
get — четвертое слово этой выходной строки).
Затем используйте lpstat, чтобы получить сведения о выполненном задании:
._. lpstat -W "completed" | grep $printJob
Kyocera-ECOSYS-P5021cdw-564 ming 2048 Sun 18 Apr 2021 11:20:56 BST
Выделение той части, которая включает дату, немного неудобно, потому что lpstat, похоже, предлагает теперь прямой способ сделать это, а дата состоит из нескольких слов. Так что, возможно, либо:
._. printJobDateString=$(lpstat -W "completed" | grep $printJob | awk '{print $4,$5,$6,$7,$8,$9}')
._. echo $printJobDateString
Sun 18 Apr 2021 11:20:56 BST
(И awk, похоже, не предлагает способа захвата диапазона — пожалуйста, поправьте меня, если я ошибаюсь).
... или сделать то же самое с помощью встроенной оболочки read
, которая по неизвестным мне причинам обрабатывает всю строку даты как одно слово (четвертое слово в выходной строке, где read помечает первые четыре слова именами a,b,c,d):
._. printJobDateString=$(lpstat -W "completed" | grep $printJob | while read a b c d; do echo "$d"; done)
._. echo $printJobDateString
Sun 18 Apr 2021 11:20:56 BST
Наконец, возможно, стоит превратить его в метку времени в секундах с начала эпохи для удобства сравнения:
._. printedDatestamp=$(date --date="$printJobDateString" +%s)
._. echo $printedDatestamp
1618741256
printJobDateString будет пустым, если lpstat не имел записи о задании в своем завершенном списке. В этом случае date будет считать, что это 1/1/1970, когда вы преобразуете его в секунды эпохи.
Хотя на самом деле, то весьма маловероятно, что ваше задание печати не попадет в список «завершенных» заданий, поскольку в этом списке, по-видимому, содержатся как отмененные, так и завершенные задания.Поэтому игнорируйте предупреждение ниже.. Ха.
Но будьте осторожны, если lpstat не имеет вашего задания печати, он вернет пустую строку. А если вы скармливаете 'date' пустую строку, он выдаст сегодняшнюю дату. И если у вас есть это в скрипте, это может ввести вас в заблуждение, заставив думать, что задание выполнено, потому что он вернет вам сегодняшнюю дату.
Например:
._. date -d @$(date --date="" +%s) +"%F %T %z"
2021-04-17 00:00:00 +0100
В то время как «date» принимает 0 как начало «эпохи» Unix (рассвет крутого времени) - 1 января 1970 г.:
._. date -d @0 +"%F %T %z"
1970-01-01 01:00:00 +0100
Это может быть более полезным указанием на невыполненную работу, чем сегодняшняя дата. Поэтому преобразуйте пустую строку в ноль (если он у вас есть) перед тем, как скармливать ее 'date', возможно, так:
._. emptyString=""
._. zero=$( [[ -z "$emptyString" ]] && echo 0 || echo "$emptyString" )
._. echo zero
0
Другими словами, сгенерируйте метку даты следующим образом:
._. printedDatestamp=$(date --date="$( [[ -z "$printJobDateString" ]] && echo 0 || echo "$printJobDateString" )" +%s)
Наконец, все шаги вместе:
._. printJob=$(lp -P "1-4" -o fit-to-page -o number-up=2 -o sides=two-sided-short-edge -o KCEcoprint=On "$fn" | awk '{print $4}')
._. printJobDateString=$(lpstat -W "completed" | grep $printJob | while read a b c d; do echo "$d"; done)
._. printedDatestamp=$(date --date="$( [[ -z "$printJobDateString" ]] && echo 0 || echo "$printJobDateString" )" +%s)
ПС
Используйте sleep
также после отправки задания на печать в цикле, который продолжается до тех пор, пока не получите пустую строку, выполняя grep-проверку вашего printJob по выходным данным lpstat -W "not-completed"
. Только затем опрашивайте lpstat -W "completed"
.
Вот: временная метка задания печати. И кто сказал, что управление печатью в Linux гуманно? Никто. Никто ничего подобного не говорил. И все, что они говорили об этом, они бормотали себе под нос.