這是我自己寫的「如何列印」,原本只是一篇小筆記,因為設定印表機的過程很累很複雜,為了怕我自己日久生疏,而寫給自己看的。後來越寫越長,寫成了完整的 Linux 列印設定教學。
本文是採用 samba - LPRng - ifhp filter - ghostscript uniprint 驅動程式搭配的列印架構。如果妳是用別的搭配方式,設定會有所不同。
本文作者是我一個人,未曾受過各個列印程式作者的授權,也未曾和各個作者討論,內文所述不能代表各列印程式的正式文件。本文或有疏失、遺漏、偏頗、錯誤之處,還請不吝告知,謝謝。
如果妳只是要把印表機分享給 Windows 工作站用,或只是要設定一個 Windows 工作站用的 print server ,完全不要在 Linux 下印表,請依下列步驟。如果妳真的是要「在 Linux 下設定印表機」,要在 Linux 下列印,或想更深入瞭解 Linux 下列印的架構,請跳過這一段。
把印表機接到 LPT1 ,做下述測試:
% echo "Hello, world!" >> /dev/lp0
如果印表機有反應,把整張紙退出,看看「 Hello, world! 」有沒有印出來。如果一切正常,繼續下一步。[1]
% tar xzf LPRng-x.x.x.tgz % cd LPRng-3.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --disable-setuid % make % make test % su $ make install
# 最簡化的 printcap 設定,只給 samba 客戶端列印使用 lp: :lp=/dev/lp0 :sd=/var/spool/lpd/%P
這時印表機應該會有反應。把整張紙退出,看看「 Hello, world! 」有沒有印出來。如果一切正常,繼續下一步。[24]$ checkpc -f $ echo "Hello, world!" | lpr
存檔後,記得要開一個 /var/spool/lpd/samba 的目錄,擁有者是 root ,權限是 1777 。[printers] comment = Printers printable = yes browsable = no public = no valid users = @users printing = lprng path = /var/spool/lpd/samba print command = /usr/bin/lpr -P%p -r %s lpq command = /usr/bin/lpq -P%p lprm command = /usr/bin/lprm -P%p %j lppause command = /usr/sbin/lpc hold %p %j lpresume command = /usr/sbin/lpc release %p %j queuepause command = /usr/sbin/lpc -P%p stop queueresume command = /usr/sbin/lpc -P%p start
如果沒有問題,重開 samba ,回到 Windows 工作站,從網路上的芳鄰中重新整理,看看能不能看得到這臺印表機。[26]$ /usr/local/samba/bin/testparm
這部份請參考 Windows 的說明,和印表機說明書的安裝設定說明。記得要印一張測試頁,測試看看。[27]
Linux 列印的基本做法如下:
圖中虛線為 Windows / samba 網路印表機列印資料傳送流程。
我們從最下層往上設定起:
把印表機接到 LPT1 ,做下述測試:
% echo "Hello, world!" >> /dev/lp0
如果印表機有反應,把整張紙退出,看看「 Hello, world! 」有沒有印出來。如果一切正常,繼續下一步。[1]
印表機硬體通訊傳輸一切正常,可以直接列印英文後,接下來我們要讓她列印 PostScript 文件。如果妳的印表機本身就是 PostScript 印表機,(那妳一定非常有錢,不然就是在公司或學校電算中心,)可以直接列印 PostScript ,可以跳過這一段。
PostScript 是列印專用的文件格式,是 1985 年由 Adobe 制定的。[2] 大多數雷射印表機都可以直接列印 PostScript 文件。不過我想妳和我的便宜噴墨(或點矩陣)印表機,應該都辦不到,所以我們繼續往下看。
Ghostscript 是 PostScript 印表機模擬程式,透過軟體模擬,可以讓非 PostScript 印表機,也能印出 PostScript 文件。如此一來,就可以把我們的廉價印表機,當成貴貴的 PostScript 印表機來用了。[3]
Ghostscript 的工作是轉譯印表指令,將 PostScript 指令,轉譯成各種印表機專用的低階列印指令,送印表機執行。因此, Ghostscript 需要知道各種印表機的指令語言。這就是所謂的「驅動程式」。有的印表機 Ghostscript 有隨附驅動程式,有的沒有。沒有隨附驅動程式的時候,妳可以上 LinuxPrinting 印表機資料庫找,有沒有別人寫過妳印表機的 Ghostscript 驅動程式,下載來用。除非是 uniprint 驅動程式,否則下載後,要再重新編譯 Ghostscript 。
uniprint (Unified Printer Drivers) 原先是設計給 Epson Stylus Color 系列的一種 Ghostscript 驅動程式規格,下載後可以直接存檔使用,不用重新編譯 Ghostscript 。 uniprint 驅動程式的附檔名是 .upp 。[4]
編輯 Makefile ,修改安裝的位置:% tar xzf gnu-gs-6.52.tar.gz 或 ghostscript-x.xx.tar.gz % cd gsx.xx % ln -s src/unix-gcc.mak Makefile
接著安裝:prefix = /usr
然後,到 /usr/share/ghostscript/ 下,解壓縮 Ghostscript 字型:% make % make test % su $ make install
$ cd /usr/share/ghostscript/ $ tar xzf ghostscript-fonts-std-x.x.tar.gz $ tar xzf ghostscript-fonts-other-x.x.tar.gz
xxxxxxxx 是妳印表機的代號;如果是 uniprint ,$ cd /usr/share/ghostscript/x.xx/examples/ $ gs -sDEVICE=xxxxxxxx -sOutputFile=/dev/lp0 tiger.ps
xxxxxxxx.upp 是 uniprint 驅動程式檔名。如果 Ghostscript 可以順利讀到驅動程式,就會印出一隻大老虎了。[7] 妳可以把這一行設定成 alias ,加在 ~/.bashrc 下:$ cd /usr/share/ghostscript/x.xx/examples/ $ gs @xxxxxxxx.upp -sOutputFile=/dev/lp0 tiger.ps
alias gs="gs -sDEVICE=xxxxxxxx -sOutputFile=/dev/lp0"
可以列印 PostScript 後,要印其她的檔案,只要統一轉為 PostScript ,就可以印了。 PostScript 的轉換程式很多也很瑣碎,安裝設定都很簡單,在這裏就不詳述了。以下列出幾種常見的 xxx2ps PostScript 轉換程式:
安裝完後,記得要測試轉換後的 PostScript 檔能不能印。
$ echo "Hello, world" | a2ps -o - | gs - $ html2ps < /usr/local/apache/htdocs/index.html | gs - $ gs mypdf.pdf $ giftopnm < mygif.gif | pnmtops | gs - $ jpegtopnm < myjpeg.jpg | pnmtops | gs - $ pngtopnm < mypng.png | pnmtops | gs - $ bmptoppm < mybmp.bmp | pnmtops | gs - $ tifftopnm < mytiff.tif | pnmtops | gs - $ ...
以後要列印,只要用 PostScript 轉換程式轉為 PostScript ,就一切 OK 囉。到此,我們已經可以「列印」了。不管要印什麼,都通行無阻。
可以列印還不夠。印不同的檔案,要跑不同的轉換程式,把檔案格式轉來轉去。這樣太麻煩了。我們需要一個智慧型程式,自動判斷檔案類型,呼叫要用的轉換程式。這就是 filter 列印資料濾鏡。 filter 的原理其實很簡單,有興趣的話,看完以下的說明,妳也可以自己寫一個試試看。
現成的 filter 有很多,比較普遍的如 lpdomatic (LPD-O-Matic)[12] 、 tops 、 magicfilter[13] 、 apsfilter[14] 、 rhs-printfilters[15] …等等。 ifhp 是 LPRng 同一個 team 寫的 filter ,我自己用的是 ifhp ,所以以下以 ifhp 來說明:
% tar xzf ifhp-x.x.x.tgz % cd ifhp-x.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man % make % make test % su $ make install
xxxxxxxx.upp 是妳下載的 uniprint 驅動程式檔名。這樣 ifhp 才能從妳指定的印表機代號,找到妳的印表機該如何設定。[ xxxxxxxx.upp ] status pjl@ pcl@ ps@ text gs_converter= \%s{gs_unidriver} gs_device=xxxxxxxx.upp
\%s{string} 會被代換為之前 string= 設定的字串。列印時, ifhp 會呼叫 /usr/bin/file 判斷檔案類型,從傳回來的結果字串,和這些樣式比對,如果符合,就執行後面設定的指令。[17] 如果後面沒有指令了,就當成最終轉換結果送出。例如:file_output_match = [ *postscript* raw \%s{gs_converter} *text* text [16] *01-* text *pcl* filter \%s{pcl_converter} *pjl* filter \%s{pjl_converter} *html* filter \%s{html_converter} *pdf* raw \%s{pdf_converter} *37)* raw \%s{pdf_converter} *jpeg* filter \%s{jpeg_converter} *gif* filter \%s{gif_converter} *png* filter \%s{png_converter} *pc_bitmap* filter \%s{bmp_converter} *tiff* filter \%s{tiff_converter} *gzip_compressed* filter \%s{gzip_decompress} *data* raw ]
"JPEG image data, JFIF standard" 符合 *jpeg* (不分大小寫),於是就執行 jpeg_converter 。妳可以依 file 執行傳回的結果字串,設計新樣式。% file myphoto.jpg myphoto.jpg: JPEG image data, JFIF standard
執行時, ifhp 會用 pipe 輸出入重導 (|) ,從標準輸入 stdin 傳入原始檔案,而從標準輸出 stdout 取得轉換結果。html_converter= /usr/bin/html2ps 2>/dev/null pdf_converter= \%s{gs_converter} jpeg_converter= /usr/bin/jpegtopnm | /usr/bin/pnmtops -noturn[18] gif_converter= /usr/bin/giftopnm | /usr/bin/pnmtops -noturn[19] png_converter= /usr/bin/pngtopnm | /usr/bin/pnmtops -noturn bmp_converter= /usr/bin/bmptoppm | /usr/bin/pnmtops -noturn tiff_converter= /usr/bin/tifftopnm | /usr/bin/pnmtops -noturn
如果印出來沒問題, ifhp 就設定好了。[20] 到此,可以告一個段落,我們終於有了一個智慧型的列印程式,可以自動視情況列印各種檔案了。妳可以把上面那一行設定成 alias ,加在 ~/.bashrc 下:$ /usr/libexec/filters/ifhp -Tdev=/dev/lp0,model=xxxxxxxx < /tmp/myfile
然後喝杯咖啡,休息一下。 ^_*'alias ifhp="/usr/libexec/filters/ifhp -Tdev=/dev/lp0,model=xxxxxxxx"
我們終於有了一個智慧型列印資料濾鏡 ifhp ,可以自動視情況分配檔案格式的轉換工作,再把最終結果送到印表機。只要用 ifhp ,要印什麼都可以印了。總算結束了吧?
還沒有。列印工作遠比想像中複雜。不只要能印,還要能「管理」:同時要印好幾個檔案的時候,妳要讓檔案排隊列印,或是把重要的檔案抽出來先印,還要把送錯了的檔案取消掉,或是在卡紙的時候,暫停列印。更何況, /dev/lp0 的權限是 660 ,我們不可能讓每個人都有權限,直接寫到 /dev/lp0 去。[21]
所以我們需要列印管理程式 LPRng ,管理所有的列印工作。
% tar xzf LPRng-x.x.x.tgz % cd LPRng-x.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --disable-setuid[22] % make % make test % su $ make install
%P 是指印表機的名稱,也就是第一行設定的 lp: 。妳可以把印表機名稱改成妳比較好記的名字,如 HPDJ670C 。 :sd= 設定的是列印佇列存放的目錄,如果還沒有建好這個目錄,要記得去 mkdir 。擁有者是 root ,權限最好和 /tmp 一樣是 1777 。# 配合 ifhp filter 和 Ghostscript uniprint 驅動程式的 printcap lp: :lp=/dev/lp0 :sd=/var/spool/lpd/%P :ifhp=model=xxxxxxxx :filter=/usr/libexec/filters/ifhp
如果使用者都是身邊的熟人,把權限放鬆一點,給大家方便。把 "ACCEPT SERVICE=C LPC=lpd,status,printcap" 這一行去掉,改成:# 限制可連線的 IP ,格式是 IP 或 IP/子網路遮罩 REJECT SERVICE=X NOT REMOTEIP=127.0.0.1,192.168.0.0/255.255.0.0 # 限制可連線的網域。 REJECT REMOTEHOST=X NOT REMOTEIP=localhost,*.your.domain
另外,要讓管理者可以刪掉印壞的文件。找到 "ACCEPT SERVICE=M SERVER REMOTEUSER=root" 那一行:# 給大家方便,讓大家自己暫停∕繼續 #ACCEPT SERVICE=C LPC=lpd,status,printcap ACCEPT SERVICE=C LPC=lpd,status,printcap,hold,release,stop,start REMOTEGROUP=users
# allow root on server to remove a job ACCEPT SERVICE=M SERVER REMOTEUSER=root ACCEPT SERVICE=M SERVER REMOTEGROUP=lp
checkpc -f 會檢查 printcap 的設定,如果有什麼問題,例如 :sd= 的目錄不存在,會試著自動修正。檢查過沒問題後,重讀 /etc/printcap 檔:$ checkpc -f
這時再列印看看 /tmp/myfile :$ lpc reread
如果沒有問題,一切就大功告成囉! ^_*'[24]% lpr /tmp/myfile
關於如何利用 lpr 、 lprm 、 lpc 、 lpq …來管理列印工作,請參考 LPRng-HOWTO 的說明。
如果妳沒有要把這臺印表機分享其她 Windows 工作站來用,可以不必看這一段。
存檔後,記得要開一個 /var/spool/lpd/samba 的目錄,擁有者是 root ,權限是 1777 。[printers] comment = Printers printable = yes browsable = no public = no valid users = @users printing = lprng path = /var/spool/lpd/samba print command = /usr/bin/lpr -P%p -r %s lpq command = /usr/bin/lpq -P%p lprm command = /usr/bin/lprm -P%p %j lppause command = /usr/sbin/lpc hold %p %j lpresume command = /usr/sbin/lpc release %p %j queuepause command = /usr/sbin/lpc -P%p stop queueresume command = /usr/sbin/lpc -P%p start
如果沒有問題,重開 samba ,回到 Windows 工作站,從網路上的芳鄰中重新整理,看看能不能看得到這臺印表機。[26]% /usr/local/samba/bin/testparm
這部份請參考 Windows 的說明,和印表機說明書的安裝設定說明。記得要印一張測試頁,測試看看。[27]
(回正文)*text* filter \%s{a2ps_converter}
(回正文)jpeg_converter= /usr/bin/imgtops2
exit 0 是因為 gif2ps 會把不嚴重的警告也以錯誤值傳回, ifhp 會誤判為轉換失敗,就不會印了。 (回正文)gif_converter= /usr/bin/gif2ps; exit 0
執行:#! /bin/sh file=/tmp/myfile ifhp=model=xxxxxxxx cat /dev/null >/tmp/t cat $file | /usr/libexec/filters/ifhp -Tdev=/tmp/t,trace,debug=2,${ifhp} 2> /tmp/trace
仔細看看 /tmp/trace ,找到問題的原因。妳可以把 debug= 的值設大一點(如 debug=10 ),以得到更詳細的偵錯資訊。 (回正文)$ sh -x /tmp/send
檢查列印記錄。若還是不行,請參考 LPRng HOWTO 的說明。 (回正文)% lpq -L
更進一步的資料請參考下列網址: