我正在寻找一种方法来查看 CUPS 中作业的时间戳。我搜索了手册页,似乎找不到它。
长期目标是拥有一个脚本,可以解析 jobID 中的时间,并自动删除超过特定年龄的任何作业 - 以避免服务器过载。我的 CUPS 服务器有超过 2000 个打印队列。
答案1
我在 U&L 网站中发现了以下两个问题,它们似乎给出了实现此目的的可能方法的提示。这2个问题:
似乎暗示你可以用来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 控制文件的目录,通常是 /var/spool/cups , you'll notice a bunch of control files in there. These files are kept as a result of the
MaxJobs 设置,未设置时默认为 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)
当然,在工作完成之前你不能说工作已经完成。所以你可能想要循环并睡眠,直到你检测到它为止。
如果您确实想要队列中的日期,也许可以执行以下操作:
当您发送打印指令时捕获您的打印作业 ID:
._. printJob=$(lp somefile | awk '{print $4}')
._. echo $printJob
Kyocera-ECOSYS-P5021cdw-564
(有必要通过 awk 解析 lp 的输出,因为 lp 似乎没有选择简单地返回打印作业):
._. lp somefile
request id is Kyocera-ECOSYS-P5021cdw-568 (1 file(s))
(awk '{print $4}'
获取该输出字符串的第四个单词)。
然后使用 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 似乎也没有提供捕获范围的方法 - 如果我错了,请纠正我)。
...或者对 shellbuilt-in 执行相同的操作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
如果 lpstat 的已完成列表中没有该作业的记录,则 printJobDateString 将为空。在这种情况下,当您将日期转换为纪元秒时,日期将假定为 1/1/1970。
其实虽然,您的打印作业不太可能不会出现在“已完成”作业列表中,因为该列表似乎收集已取消的作业以及已完成的作业。所以忽略下面的警告。哈。
但要小心,如果 lpstat 没有您的打印作业,它将返回一个空字符串。如果您向“日期”提供一个空字符串,它会输出今天的日期。如果您在脚本中包含该内容,它可能会误导您认为工作已经完成,因为它会给您今天的日期。
例如:
._. date -d @$(date --date="" +%s) +"%F %T %z"
2021-04-17 00:00:00 +0100
而 'date' 将 0 作为 Unix 'epoch' 的开始(美妙时光的黎明) - 1970 年 1 月 1 日:
._. 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
发送打印作业后,也可以在一个循环中使用,通过在lpstat -W "not-completed"
.然后才轮询lpstat -W "completed"
。
其中:打印作业的时间戳。而谁说linux打印控制人性化呢?没有人。没有人说过这样的话。他们对此所说的一切都小声嘀咕。