top
Loading...
用lpadmin打印多種內容形式
font color="#CC0000">概述

設置一個能夠處理多種內容形式的打印服務器,似乎并不是一個困難的任務--實際上也不難,只要考慮一下第三方軟件。當你決定只用lpadmin來做時,困難就來了。Unix系統管理專家Errol Fouquet 和Robert Krumm 通過本文指導你用一個經檢驗過的方法,來設置一個打印服務器,使其能夠成功地處理純文本、PostScript、可打印二進制碼(pcl,rtl)等內容形式的文件。

作為UNIX系統管理員在與雇主簽約時,雇主要求他們在給客戶提供的服務中,要有一項是打印與繪圖的技術支持。一個特殊的客戶,他的打印環境相當復雜,包括八臺36英寸HP繪圖儀,一臺24英寸HP繪圖儀,大約20臺HP DeskJet 1600c繪圖儀,以及大約20臺HP 3si/4si/5si 打印機。所有的設備運行LPD,有PostScript 驅動程序,作為網絡打印機使用TCP/IP協議來訪問。打印機網卡有HP JetDirect 和XCD XJet 卡各占一半。

我們在一臺Sun Ultra Enterprise 450 上運行Zeh Graphic Systems 的 ZPS繪圖軟件,來支持幾個輸出多種圖形格式的應用程序。我們還要支持從幾個其他的應用發出的LPD命令,以及用戶發自Netscape應用程序的打印,還有用戶在命令行下發出的打印命令。在我們的環境中,打印客戶幾乎都是SUN的服務器和工作站,數目有近200個。我們還有一臺Windows NT 服務器,運行Citrix Winframe,也是一個打印客戶。
<
通過Zeh軟件繪圖的應用程序使用Ultra 450 作為緩沖池,除此以外,所有其他的打印請求都從客戶直接傳送到網絡打印機。從功能上講,這種方式工作得很好,能夠打印所有我們需要的內容形式,包括:文本,PostScript,和可打印二進制文件(pcl 和 rtl)。問題是這種設置帶來一個管理惡夢。像GIF 或 JPEG這樣龐大而又不可接受的二進制文件,經常會浪費大量的紙張,而我們又沒有簡單有效的辦法來確定打印請求是從那里發出的。我們只知道大樓內的一臺工作站或是服務器,正在向打印機發送有害的工作任務。不幸的是,標題頁并不是一個選擇,因為用戶不愿浪費紙張(反語,哈哈?)。

我們曾經試圖寫一個 shell script程序,讓它掃描大樓內所有的機器,并把行為報告給特定的打印機。用這些信息我們就可以執行Cancel命令。但是這個方法異常緩慢,效率低下。

客戶自己的技術策略顯示,解決辦法就是為UNIX環境寫一個打 衿鞒絳潁遣唄員舊礱揮形庵峙渲錳峁┫附凇A磽猓罱蒘print Paranet做的NOMAN(network operations management網絡操作管理)評估也認為,應該開發一個打印服務器程序來滿足客戶的需求。

我們知道一個打印服務器是正確的選擇。如果我們能夠設置好它,所有的打印請求都可以從一臺機器上管理,這會極大地簡化整個過程。 但是這又非常困難,我們難以接受。

嘗試一:試驗和錯誤

最初,我們想建立一個標準的Solaris打印緩沖。我們指定一臺測試機器作為測試打印服務器,取名 nolsn099 (一臺運行Solaris 2.6的Ultra 1) ,并開始幾個測試。開始用來測試的打印機是一臺HP 1600c,在 NIS/DNS環境中稱為no1316p。

對每一種服務器設置,客戶機用命令行lpadmin -p no1316p -s nolsn099!no1316p 設置來訪問打印機/繪圖儀。
<
服務器設置1:

lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS
-I PostScript -v /dev/null -i /usr/lib/lp/model/netstandard

結果:客戶機能夠打印 PostScript和二進制文件,但是文本文件會出現樓梯效果。

服務器設置2:

lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown
-I any -v /dev/null -i /usr/lib/lp/model/netstandard

結果:客戶機能夠打印文本文件,但是 PostScript和二進制文件打印了成垃圾。

服務器設置3:

lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS -I text
-v /dev/null -i /usr/lib/lp/model/netstandard

結果:客戶機能夠打印文本文件和 PostScript文件,但是rtl和pcl文件打印了成垃圾。
<
服務器設置4:

lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown
-I PostScript,text,simple -v /dev/null
-i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown
-I any,PostScript,simple -v /dev/null
-i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS
-I any -v /dev/null -i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown
-I text,simple -v /dev/null
-i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T hplaser
-I text,simple -v /dev/null
-i /usr/lib/lp/model/netstandard


結果:以上幾種設置,客戶機能夠打印 PostScript和二進制文件,但是文本文件會出現樓梯效果。

服務器設置5:

lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS
-I any -v /dev/null -i /usr/lib/lp/model/netstandard
<
結果:客戶機能夠打印文本文件和 PostScript文件,但是rtl和pcl文件打印成垃圾。

我們試驗了幾種組合,但是不能成功地打印所有的三種格式。lpadmin的幫助文檔建議可以使用多個 -T選項。我們認為真正需要的是 -T unknown,PS選項,但不幸的是,lpadmin 不允許 unknown 同其他的選項同時出現。

我們得出結論:使用 Solaris lpadmin 提供的標準選項,我們可以設置打印機來處理:

只有文本文件

文本和PostScript

PostScript和可打印二進制文件(pcl和rtl)

下一步我們打電話到SUN的軟件支持部門。很幸運我們找到一個能干的技術支持人員,他給了我們一個看起來可行的方案。盡管他承認這是一個平庸的方法,但他確認它能行。方案包括在打印服務器上為每臺打印機設立兩個打印隊列,然后應用兩個打印緩沖。第一個設備起過濾器的作用,然后將其輸出定向到網絡打印機。(我們采用printname printname-r的命名規則)

以下是具體步驟:

第一步:在服務器上建立過濾設備

$ lpadmin -p no1316p -v /dev/null -i /usr/lib/lp/model/standard
$ enable no1316p
$ accept no1316p
<
第二步:編輯新創建的界面描述文件(/etc/lp/interfaces/no1316p)

找到以 case $TERM in 開頭的 case 語句
對 *) 條件,注釋掉包含 FILTER=${LPCAT} 的一行
插入一行 FILTER=/bin/unix2dos | lp -s -d no1316p-r

第三步:建立網絡服務器(no1316p-r)

$ lpadmin -p no1316p-r -o protocol=bsd,dest=no1316p -v /dev/null
-i /usr/lib/lp/model/netstandard
$ enable no1316p-r
$ accept no1316p-r

:沒有指定 -T -I 選項,使用缺省的 "unknown" " any"

完成以上步驟后,似乎打印機正常工作了。命令unix2dos修正了文本文件的樓梯現象,而且我們也能打印PostScript, pcl, 和 rtl 文件。我們幾乎準備慶祝了,這時我們注意到pcl和rtl 文件的打印質量極其糟糕。命令unix2dos搞壞了二進制格式!

我們又打回電話給SUN。這一次我們同幾位SUN的工程師開了一個電話會議,報告我們的需求和發現。他們建議使用一個lpadmin命令(我們曾經使用過)來設置打印機。當我告訴他們這會導致文本文件出現樓梯效果時,其中兩個工程師心照不宣地嘆息了一聲。他們答應查一下。同時,我們也繼續尋找答案。
<
嘗試二:紅色磁帶

接下來,我們試著使用Hewlett-Packard的 JetAdmin 軟件--SUN的推薦方案。我們設置一臺機器作為打印服務器,然后安裝JetAdmin軟件。棒極了。我們能夠完美無缺地打印這三種文件。我們能夠設置客戶機,以這臺服務器做打印緩沖;而且軟件提供了信息,用來管理不必要的打印作業。我們找到了解決方案!錯了,我們被告知不能替換XCD卡。

還沒有得到SUN公司的反饋信息,我們選擇重新試驗"double spooling"雙緩沖的方案

嘗試三:重試雙緩沖

雙緩沖方案已經接近成功,我們不能完全放棄它。只是unix2dos的限制妨礙成功。如果我們能檢查輸入文件,只對非二進制文件執行unix2dos,那就成了。我們寫了一個簡單的Perl程序(unix2dos.pl)來做這些:

#!/opt/bin/perl
# open standard input
open(FOO, "-");
# test if binary
if ( -B FOO) {
while () {
print $_;
}
}
<
# if not binary.. perform unix2dos filtering
else {
while () {
s///; print;
}
}
close(FOO);

界面文件中的那一行改成如下:

FILTER=/opt/utils/unix2dos.pl | lp -s -d no1316p-r

可以了。我們可以毫無問題地打印這三種文件了。不幸,由于雙重緩沖,在 no1316p-r中的打印作業不再具有有意義的名字和所有者了。例如,當一個客戶打印一個文件,比如/etc/passwd;在打印服務器上執行lpq -Pno1316p ,會有以下結果:

$ lpq -Pno1316p
Rank Owner Job File(s) Total Size
active dlister 313 /etc/passwd 522 bytes
<
但是當no1316p過濾了這個作業,并把它重定向到 lp -s -dno1316p-r后,在打印服務器上執行lpq -Pno1316p-r ,我們會有以下結果:

$ lpq -Pno1316p-r
Rank Owner Job File(s) Total Size
active lp 1629 1629-1 536 bytes

沒有恰當指定的文件名和所有者,用戶不能跟蹤在打印隊列里的文件,管理員也不能從隊列中刪除打印作業。

嘗試4:找一個折衷

因為我們已經成功地打印這三種文件,現在我們需要的只是網絡打印機隊列中的有意義的信息。我們知道,當打印作業在過濾隊列(如no1316p)中排隊時,原始的文件名和用戶名是可用的。我們必須找出一個辦法,保存這些信息,并把它們與在實際的網絡打印機隊列(如no1316-r)中排隊的打印作業對應起來。

我們知道,當一個作業通過過濾隊列時,lp子系統會返回我們感興趣的信息。所以顯而易見,我們應該能夠通過環境變量利用這些信息。我們感興趣的變量可以用在過濾隊列的界面描述文件中:${request_id}, ${user_name},${files}, 和 ${flist}。但是我們仍然面臨一個問題:把這些信息同實際的網絡打印機隊列的lpq聯系起來。我們需要一種手段,記錄那些進入過濾隊列的請求;還需要一個方法,把網絡打印機隊列中的各個項映射回初始的信息。
<
我們最終采用的策略是,將輸入過濾到一個臨時文件,文件名中包含初始的${request_id}。然后重定向該臨時文件的lp,現在網絡打印機隊列的lpq 信息中以文件名的形式包含了初始的${request_id} 。只剩下log文件了。我們進一步修改過濾隊列的界面描述文件,在if [ -z "${FILTER}" ]后加上以下程序:

# write current request_id user_name and flist to logfile
# if the flist variable is null, we are printing a single file,
# therefore echo ${files}
# else echo ${flist}
if [ "$flist" = "" ];
then
echo "${request_id} ${user_name} ${files}"
$gt; $gt; /var/spool/lp/save_dir/logs/request.log
else
echo "${request_id} ${user_name} ${flist}"
$gt; $gt; /var/spool/lp/save_dir/logs/request.log
fi

我們把創建臨時文件的工作并入unix2dos.pl程序中。新的程序稱為lp.pl:

#!/opt/bin/perl
# open standard input
open(FOO, "-");
# create temp file for writing
open(OUT, "$#@62;/var/spool/lp/save_dir/tmp/$ARGV[0].$$");
# if input stream is binary do not filter
if ( -B FOO) {
while () {
<
print OUT $_;
}
}
# else filter the line unix2dos style
else {
while () {
s///; print OUT;
}
}
close(FOO);
close(OUT);
# send print request
system("/bin/lp -s -d $ARGV[1] /var/spool/lp/save_dir/tmp/$ARGV[0].$$");

下一步,我們向lp.pl傳遞兩個參數:${request_id}, 和網絡打印機。這個程序生成一個名字為:

${request_id}."進程的pid號"的過濾后的臨時文件,并lp這個臨時文件。然后,我們把過濾隊列界面文件中的:

FILTER=/opt/utils/unix2dos.pl | lp -s -d no1316p-r

這一行,替換成:

FILTER="/var/spool/lp/save_dir/sbin/lp.pl ${request_id} no1316p-r"
<
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗