9.4. 簡單的印表機設定

這一節將說明如何連接印表機及設定 LPD。包括:

如果你要設定的是網路印表機,請參考 使用網路資料傳輸界面的印表機 這一節。

雖然這一節叫做 ``簡單的印表機設定'',但其實是蠻複雜的。 讓你的印表機可以配合 LPD spooler 是設定工作中最難的一部份。 一但你的印表機可以正常工作了,較進階的功能如列印 header pages 和印表機使用情形統計反而較容易設定。

9.4.1. 硬體設定

這一節說明有哪些方法可以將印表機連到我們的個人電腦上; 有哪些通訊埠、連接線以及 kernel 的設定在 FreeBSD 下是必需設定的。

如果你的印表機在你使用的電腦上可以透過其他作業系統來印列, 你也許可以跳過這一節直接到 軟體設定那一節。

9.4.1.1. 通訊埠及連接線

幾乎所有可以和 PC 連接的印表機能支援下列兩種或是其中一種界面:

  • 序列 界面的印表機透過序列埠和電腦之間傳送資料。 序列界面的配備及連接線可以容易的取得及裝設, 但是序列界面有時需要較特別的連接線及較複雜的設定。

  • 並列 界面的印表機透過並列埠和電腦之間傳送資料。 並列界面在市場上很普遍,連接線也很容易取得, 但是不容易自己製做。利用並列埠連接印表機十分的容易, 通常不需要設定額外的通訊參數。

    並列界面有時也稱做 ``Centronics'' 界面, 這是根據印表機上面的接頭而命名的。

一般而言,序列埠的速度比並列埠慢。 並列埠通常只有單向傳輸(從電腦到印表機),而序列埠通常都是用雙向傳輸。 較新的並列埠也可以從印表機那邊取得資料, 不過很少有印表機需要將資料送回電腦。FreeBSD 目前並不支援並列埠雙向傳輸。

通常,只有使用 PostScript 的印表機才需要用到雙向傳輸。 PostScript 印表機可以說是十分的複雜。事實上,PostScript 的列印工作常常是由程式將工作送到印表機處理後,並不列印出來, 而是將結果再傳回電腦。PostScript 也使用雙向傳輸將錯誤傳回電腦, 比如說 PostScript 程序有問題或是印表機卡紙。 機器上的使用者可能會需要這些資訊。更進一步的,PostScript 印表機統計列印情形最好的方式就是使用雙向傳輸,比如說: 你可先詢問印表機自開機以來一共印過了幾張,然後送出使用者要印的東西, 印完後再詢問一共印了幾張,由此就可得知得向使用者收多少紙張的錢。

那麼,你該選擇哪一種界面呢?

  • 如果你需要雙向傳輸,那麼就選擇使用序列埠。FreeBSD 目前並不支援並列埠上的雙向傳輸。

  • 如果你不需要雙向傳輸,那麼, 你只要選擇你的印表機支援的界面即可,當然最好是可以用並列埠, 而將序列埠留給其他的用途 --比如連接終端機或數據機--通常並列埠傳輸比較快, 設定起來也較容易。

  • 最後,還是不曉得怎麼選的話,就看哪個能用就接哪個吧。

9.4.1.2. 並列埠

用 Centronics 連接線透過並列埠連接印表機和電腦。印表機的手冊、 電腦的手冊這兩者都可以給你足夠的安裝說明。

記住你所使用的並列埠。在 FreeBSD 裡,第一個並列埠是 /dev/lpt0;第二個則是 /dev/lpt1,依此類推。

9.4.1.3. 序列埠

用適當的連接線透過序列埠連接印表機和電腦。印表機的手冊、 電腦的手冊這兩者都可以給你足夠的安裝說明。

如果你不確定你的連接線是否為``合適的序列埠連接線'', 你可以試試下面幾種不同用途的線:

  • 連接數據機的線。 這種線是一個接腳對一根接腳直接對接的。 這種線也叫做 ``DTE-to-DCE'' 連接線。

  • Null-modem 連接線大部份是一個接腳對一個接腳直接對接, 而有少部份接腳相互交換(如 send data 和 receive data);有少部份接腳則是兩端皆是短路。 這種線也叫做 ``DTE-to-DTE'' 連接線。

  • 序列印表機連接線, 某些不常見的印表機需要這種線。這種線類似 null-modem 連接線,但是有些訊號是送到相對應的接腳而不是兩端短路。

你也得為印表機設定通訊參數,通常可以利用印表機上的控制面板或是 DIP 開關設定。選擇你的電腦和印表機同時支援的最高傳輸速率 (單位為 bps,bits per second,也稱做 baud rate)。 選擇 7 或 8 的資料位元;無、奇數或偶數的同位元檢查; 1 或 2 停止位元。同時也選擇流量控制的方式:無、XON/XOFF (也稱做 ``in-band'' 或 ``軟體'') 流量控制。 記得你的軟體設定也要使用同樣的值。

9.4.2. 軟體設定

這一節說明如何設定 FreeBSD 下的 LPD spooling 系統,使其能列印。

下列是所需的步驟:

  1. 如果需要的話,設定你的 kernel,使該連接埠可被印表機使用。 設定 Kernel 這一節將告訴你需要做些什麼。

  2. 如果你使用的是並列埠,那麼你得設定並列埠的通訊模式。 設定並列埠的通訊模式 這一節有詳細的說明。

  3. 測試作業系統是否可以將資料送給印表機。 檢查印表機連線狀況 這節將給你一些關於這一方面的建議。

  4. 修改 /etc/printcap 以正確設定 LPD。 /etc/printcap 設定檔 將告訴你如何做。

9.4.2.1. 設定 Kernel

作業系統的 kernel 為了能配合某些裝置而需要重新編譯。 而序列埠和並列埠就是這些裝置之一。如果你的 kernel 目前並不支援你想用的序列埠或並列埠,那麼你可能需要將他們加入你的 kernel 設定並重新編譯。

若要檢查你的 kernel 目前是否支援序列埠,你可以用這個命令:

    # dmesg | grep sioN

其中N是序列埠的編號,從 0 開始計算。 如果你得到的結果類似下面這個樣子:

    sio2 at 0x3e8-0x3ef irq 5 on isa
    sio2: type 16550A

表示你的 kernel 支援這個通訊埠。

若要檢查你的 kernel 目前是否支援並列埠,你可以用這個命令:

    # dmesg | grep lptN

其中N是並列埠的編號,從 0 開始計算。 如果你得到的結果類似

    lpt0 at 0x378-0x37f on isa
表示你的 kernel 支援這個通訊埠。

你可能會需要重新設定你的 kernel 使得作業系統可以辨認並使用你連接印表機的並列埠或序列埠。

若要讓你的 kernel 支援序列埠,請參考關於重新編譯 kernel 的那一節。若要讓你的 kernel 支援並列埠,請參考關於重新編譯 kernel 的那一節以及下一節。

9.4.2.1.1. 為通訊埠新增 /dev 下的設備檔案

即使 kernel 已經支援你所需的並列埠或序列埠了,你仍然需要一支 程式界面在系統裡協助傳送及接收資料。 這也是 /dev 裡設備檔案存在的目的。

若要在 /dev 目錄下為你的通訊埠建立相對應的裝置檔案:

  1. su(1) 命令切換成 root。

  2. 更改目前的目錄到 /dev 下:

        # cd /dev
  3. 輸入:

        # ./MAKEDEV port

    其中 port 是你想要建立的裝置檔案名稱。若是第一個並列埠,你可以用 lpt0,若是第二個並列埠,你可以用 lpt1,依此類推。如果是第一個序列埠, 你可以用ttyd0 而用 ttyd1 如果是第二的序列埠。依此類推。

  4. 輸入:

        # ls -l port

    以確定你剛剛是否有建立成功。

9.4.2.1.2. 設定並列埠的通訊模式

當你決定要用並列埠時,在 FreeBSD 下你可以決定要用中斷驅動 (interrupt-driven)或是輸詢(polled)的方式與印表機溝通。

  • 中斷驅動是 GENERIC kernel 裡預設的方式。若選擇這個方式,作業系統將利用 IRQ 來判斷印表機是否已經準好接收資料。

  • 輪詢 的方式則是由 作業系統一直重覆的去詢問印表機是否已經準備好可以接受資料。 如果印表機已經準備好了,那麼 kernel 再將要列印的資料送過去。

中斷驅動的方式較快但是要佔用一個 IRQ。 你可以從上述兩者任選一個可以正常工作的來使用。

設定通訊模有兩種方式:設定 kernel 或是使用 lptcontrol(8) 這個程式。

若要從 kernel 裡設定:

  1. 編輯你的 kernel 設定檔。找出或是自行加入 lpt0 這一項。如果你要設定使用第二個並列埠, 那就加入 lpt1 這一項。 若是第三並列埠就用 lpt2,依此類推。

    • 如果你要設定使用中斷驅動模式,那麼要指定 irq

          device lpt0 at isa? port? tty irq N vector lptintr

      其中 N 是你並列埠所使用的 IRQ 編號。

    • 如果你要用輪詢模式,那麼就不要指定 irq

          device lpt0 at isa? port? tty vector lptintr
  2. 將設定檔儲存好後,重新編譯、安裝 kernel 並重新開機。 你可以參考 kernel configration那一節裡更詳細的說明。

若你想用 lptcontrol(8) 來設定通訊模式

  1. 輸入:

        # lptcontrol -i -u N

    lptN 設定為中斷驅動模式。

  2. 輸入:

        # lptcontrol -p -u N

    lptN 設定為輪詢模式。

你可以把上述的命令加到你的 /etc/rc.local 檔裡使得每次開機時都可以自動設定。你可以查看 lptcontrol(8) 以得到更多有關的資訊。

9.4.2.1.3. 檢查印表機連線狀況

在設定 spooling 系統之前,你應該先確定你的作業系統可以成功的 將資料送到你的印表機。將印表機的連線和 spooling 系統分開來測試 會較容易。

你可以送一些文字來測試你的印表機。印表機應該會馬上將他們收到 的資料印出來。lptest(1) 這個程式會送 96 行每行 96 個 ASCII 文字的資料給你的印表機以協助測試。

使用 PostScript (或是其他語言) 的印表機測試起來較複雜。 我們得先寫一個較小的測試程式,像下面這樣:

    %!PS
    100 100 moveto 300 300 lineto stroke
    310 310 moveto /Helvetica findfont 12 scalefont setfont
    (Is this thing working?) show
    showpage

Note: 注意:上面這個小程式是給使用 PostScript 的印表機用的, 不能給比如說 Hewlett Packard 公司的 PCL 語言使用。PCL 語言可以讓你可以列印純文字同時裡面夾雜 PCL 特別的命令。 PostScript 不能直接印純文字,因此對於這樣的印表機, 我們必需做一些特別的設定。

9.4.2.1.3.1. 檢查並列埠印表機

這一節將告訴你如何檢查 FreeBSD 是否可以使用接在並列埠的印表機。

測試並列埠上的印表機:

  1. su(1) 命令切換成 root。

  2. 將資料傳送給印表機。

    • 如果這個印表機可以直接列印純文字,請使用 lptest(1)。輸入:

          # lptest > /dev/lptN

      其中 N 是你印表機所連接的並列埠。從 0 開始計算。

    • 如果這個印表機使用 PostScript 或其他的印表機語言,那麼送一個小小的測試程式給印表機。 輸入:

          # cat > /dev/lptN

      然後,一行接著一行,小心的 把你的命令打進去,因為你按下 ENTER 後,就無法再修改了。 當你輸入完畢後,按 CONTROL+D 或是其他產生檔案結尾字元的按鍵。

      或者是你可以將你的測試測程放在一個檔案裡並輸入:

          # cat file > /dev/lptN

      其中 file 就是儲存你測試程式的檔名。

你應該可以看到有一些東西印出來了。 如果印出來的資料看起不大正確,別擔心, 我們稍待一會就修正他們。

9.4.2.1.3.2. 檢查序列埠印表機

這一節將告訴你如何檢查 FreeBSD 是否可以使用接在序列埠的印表機。

測試序列埠上的印表機:

  1. su(1) 命令切換成 root。

  2. 編輯 /etc/remote 這個檔,並加入下列幾行:

        printer:dv=/dev/port:br#bps-rate:pa=parity

    其中 port 指的是哪一個序列埠 (ttyd0ttyd1、等等。) ,bps-rate 指的是該序列埠的傳輸速度,而 parity 是設定印表機是否需要同位元檢查(這個值可以是 evenoddnonezero)。

    下面這個例子是一台連接在序列埠上以 19200 bps 傳輸同時不使用同位元檢查的印表機設定方式:

        printer:dv=/dev/ttyd2:br#19200:pa=none
  3. tip(1) 命令連上印表機。輸入:

        # tip printer

    如果失敗的話,再次編輯 /etc/remote 這個檔同時以 /dev/cuaaN 取代 /dev/ttydN

  4. 將資料傳送給印表機。

    • 如果這個印表機可以直接列印純文字,請使用 lptest(1)。輸入:

          ~$lptest
    • 如果這個印表機使用 PostScript 或其他的印表機語言, 那麼送一個小小的測試程式給印表機。一行接著一行, 非常小心的將程式輸入, 因為倒退鍵或是其他的編輯時常用的按鍵, 對印表機可能有特殊的意義。 最後你可能要打一個給印表機的檔案結尾字元,讓他知道 程式結束了。對 PostScript 的印表機來說,是用 CONTROL+D 鍵。

      或者是你可以將你的測試測程放在一個檔案裡並輸入:

          ~>file

      其中 file 就是儲存你測試程式的檔名。用 tip(1) 將這個檔送給印表機後,而按檔案結尾字元。

你應該可以看到有一些東西印出來了。 如果印出來的資料看起不大正確,別擔心,我們稍待一會就修正他們。

9.4.2.2. 啟用 Spooler: 編輯 /etc/printcap 設定檔

到此為止,你的印表機應該已經連接好了,你的 kernel 應該也設定無誤了,而且你也可以傳送資料給印表機了。現在, 我們應該可以開始設定 LPD 來控制印表機了。

LPD 的設定檔是 /etc/printcap。每當 spooler 被使用時,LPD spooling 系統就會來讀這個檔, 所以只要這個檔一被修改,馬上就會生效。

編輯 printcap(5) 這個設定檔是很簡單的。 用你喜歡的編輯器對 /etc/printcap 這個設定檔做修改就可以了。這個檔的格式寫法和其他的設定檔如 /usr/share/misc/termcap/etc/remote 是相同的。 關於這些設定檔的格式,請參考 cgetent(3)

要建立一個簡單的 spooler 設定,請按照下列步驟:

  1. 為你的印表機選擇一個名字 (以及一些方便的別名),並把他們放在 /etc/printcap 這個檔裡。請參見 為印表機取名這一節。

  2. sh 關鍵字關閉列印 header pages 的功能 (預設是打開此功能)。請參見 不列印 Header Pages 這一節。

  3. sd 關鍵字指定一個目錄給 spooler 用。 請參見 建立 Spooling 目錄 這一節。

  4. /etc/printcap 設定檔裡用 lp 關鍵字指定印機連接埠在 /dev 下使用的裝置檔案。請參見 辨認印表機裝置這一節。 如果你的印表機是接在序列埠,那麼你可以用 fsfcxs 以及 xc 等關鍵字來設定通訊參數。請參見 設定 Spooler 的通訊參數

  5. 安裝輸入文字過濾程式;請參考 安裝文字過濾程式 這一節。

  6. 利用 lpr(1) 命令列印以測試設定是否正確;請參見 測試疑難排解 這兩節。

Note: 使用特定語言的印表機,比如說 PostScrit 印表機,無法直接列印 純文字。上述以及接下來要介紹的方法將假設你所要列印的檔案都是 不需要轉換就能讓印表機直接了解的。

使用者通常會期望他們可以直接將純文字的資料直接由印表機輸出, 而使用 LPD 列印的程式通常也是這麼假設。 如果你的印表機使用某個特定的印表機語言, 且你希望可以同時處理特定印表機語言的資料 以及純文字的資料, 那麼你應該要另外再多安裝一項之前未提到的東西:純文字轉成 PostScript(或其他印表機語言)的自動轉換程式。 在 PostScript 印表機上列印純文字 這一節將告訴你要怎麼做。

9.4.2.2.1. 為印表機取名

第一就是為你的印表機取一個名字。此外, 你也可為你的印表機取很多別名,因此, 你要取符合功能的名字或是古怪的名字都可以。

/etc/printcap 裡定義的印表機, 至少要有一部取 lp 別名。這是預設的印表機名稱。 如果使用者沒有環境變數 PRINTER 設定印表機的名稱且在 LPD 的命令也沒有指定任何印表機的話,那麼別名為 lp 的印表機就會被視為預設的印表機。

通常,我們會將一台印表機的最後一別名取為他的全名, 包括製造商以及型號。

當你將印表機的名稱及別名設定在 /etc/printcap 檔裡時, 印表機的名稱一定要放在最左邊的欄位。其他的別名則以垂直的線(|)分開, 而在最後一個別名之後加一個冒號(:)。

在下面的例子裡,我們大略描述一下 /etc/printcap 的骨幹。 這個範例裡定義了兩台印表機。(Diablo 630 以及 Panasonic KX-P4455 PostScript 雷射印表機。):

    #
    #  /etc/printcap for host rose
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:
    
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:

在這個例子裡,第一台印表機取名為 rattan 而他的別名有 linediablolp 以及 Diablo 630 Line Printer。這台印表機有 lp 這個別名,因此他也是設預的印表機。 第二台取名為 bamboo,而他的別名有 psPSSpanasonic 以及 Panasonic KX-P4455 PostScript v51.4

9.4.2.2.2. 不列印 Header Pages

LPD spooling 系統預設是為每個列印工作列印 header page 的。Header page 包括了送出列印工作的使用者名稱、送出工作的機器名稱以及工作的名稱。 不幸的是,這些額外的訊息可能會妨礙我們做簡單的印表機設定測試, 因此我們想要不列印 header pager。

/etc/printcapsh 關鍵字為特定的印表機設定不列印 header pages。 這裡有一個在 /etc/printcap 裡使用 sh 的範例:

    #
    #  /etc/printcap for host rose - no header pages anywhere
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :sh:
    
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :sh:

注意我們使用的正確格式:印表機定義的第一行得從第一個字開始寫, 而其後的每一行用 TAB 鍵往內縮一格。 而一行若寫不完需要接到下一行時,則以反斜線字元結尾。

9.4.2.2.3. 建立 Spooling 目錄

下一步就是建立一個spooling 目錄, 一個在列印時會需要用到以及存放一些 spooler 需要的檔案的地方。

通常我們會將 spooling 目錄指定在 /var/spool 目錄之下。你不需要備份 spooling 目錄,而建立他也只要以 mkdir(1) 命令即可。

通常我們會將 spooling 目錄以印表機的名稱建立,如下所示:

    # mkdir /var/spool/printer-name

然而,如果在你的網路之中有很多印表機的話, 你也許會希望將所有的 spooling 目錄放在一個 LPD 專用的目錄之下的話。 我們以我們的範例印表機為 rattanbamboo 為例:

    # mkdir /var/spool/lpd
    # mkdir /var/spool/lpd/rattan
    # mkdir /var/spool/lpd/bamboo

Note: 如果你關心的是使用者列印資料的隱私,那麼你應該要將 spooling 目錄的權限做適當的設定。Spooling 目錄應該要屬於 daemon 這個使用者同時並允許他讀、寫及搜尋,而其他人都無法存取此目錄。 因此,我們應該要這樣設定:

    # chown daemon.daemon /var/spool/lpd/rattan
    # chown daemon.daemon /var/spool/lpd/bamboo
    # chmod 770 /var/spool/lpd/rattan
    # chmod 770 /var/spool/lpd/bamboo

最後,在 /etc/printcap 檔裡, 你可以用 sd 關鍵字來指定 spooling 的目錄:

    #
    #  /etc/printcap for host rose - added spooling directories
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :sh:sd=/var/spool/lpd/rattan:
    
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :sh:sd=/var/spool/lpd/bamboo:

注意印表機的名字一定是在定義第一行的第一個字, 而其他行皆要以 TAB 縮排。若需要換行則需要在行末加上反斜線字元。

如果你沒有用 sd 指定 spooling 目錄,那麼 系統預設的 spooling 目錄將會是 /var/spool/lpd

9.4.2.2.4. 辨認印表機裝置

為通訊埠新增 /dev 目錄下的設備檔案這一節裡,我們在 /dev 目錄下選定了要給 FreeBSD 使用與印表機溝通的連接埠。現在我們要告訴 LPD 這項資訊。當 spooling 系統有工作要列印時, 他將會告訴過濾程式程式(負責送資料給印表機)使用指定的裝置。

/etc/printcaplp 關鍵字指定使用 /dev 下的裝置名稱。

在我們的範例裡,我們設定 rattan 使用第一個並列埠,而 bamboo 使用第六個序例埠。 因此在 /etc/printcap 我們設定:

    #
    #  /etc/printcap for host rose - identified what devices to use
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :sh:sd=/var/spool/lpd/rattan:\
            :lp=/dev/lpt0:
    
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :sh:sd=/var/spool/lpd/bamboo:\
            :lp=/dev/ttyd5:

如果你在 /etc/printcap 裡沒有用 lp 關鍵字指定要使用哪個通訊埠,LPD 將會使用 /dev/lp 為預設的通訊埠。 /dev/lp 目前在 FreeBSD 中並不存在。

如果你現在安裝的印表機是連接在並列埠上,那麼請跳至 安裝文字過濾程式 這一節,否則,請按照下面這一節繼續設定。

9.4.2.2.5. 設定 Spooler 的通訊參數

對於連接在序列埠上的印表機,LPD 得設定傳輸速率、同位元檢查、 以及其他的通訊參數使得過濾程式能送資料到印表機上。 這是較有利的因為:

  • 你只要編輯 /etc/printcap 就可以使用不同的通訊參數。不需要去重新編譯你的過濾程式程式。

  • 允許 spooling 系統在多台印表機、 多種不同通訊參數設定的情況下用同一個過濾程式程式。

/etc/printcap 設定檔裡,下列關鍵字控制 lp 關鍵字所指定的通訊埠:

br#bps-rate

設定通訊埠傳輸速度為bps-rate 其中 bps-rate 可以是 50、75、110 、134、150、200、300、600、1200、1800、2400、4800、9600、 19200 或是 38400 bit-per-second。

fc#clear-bits

開啟通訊埠後,清除 sgttyb 結構裡的旗標位元 clear-bits

fs#set-bits

設定 sgttyb 結構裡的旗標位元 set-bits

xc#clear-bits

開啟通埠後,清除 local 模式位元 clear-bits

xs#set-bits

設定 local 模式位元 set-bits

關於 fcfsxc 以及 xs 關鍵字各個 bit 的說明,請參考 /usr/include/sys/ioctl_compat.h

當 LPD 開啟由 lp 所指定的通訊埠時,會先讀取 sgttyb 這個結構,然後清掉 fc 關鍵字所指定的位元再設定由 fs 關鍵字所指定的位元。設定完成後, 才開始使用這個結構。同樣的,對 local 模式位元設定也是以一樣方式處理。

讓我們在我們的例子裡為第六個序列埠設定這些位元。 我們將會將傳輸速率設定成 38400 bps。而在旗標位元方面,我們會設定 TANDEM、ANYP、LITOUT、FLUSHO 以及 PASS8 這些位元。而 local 模式位元,我們將設定 LITOUT 以及 PASS8 位元:

    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :sh:sd=/var/spool/lpd/bamboo:\
            :lp=/dev/ttyd5:fs#0x82000c1:xs#0x820:

9.4.2.2.6. 安裝文字過濾程式

我們現在可以開始設定 LPD 用什麼文字過濾程式送工作給印表機。 一個文字過濾程式也稱做 輸入用過濾程式,當 LPD 有東西要列印時,他就會執行這個程式。當 LPD 執行這個程式時,他會將過濾程式的標準輸入設為欲列印工作的標準輸入, 而過濾程式的標準輸出則送給以 lp 關鍵字指定的通訊埠。 因此過濾程式程式必需要能從標準輸入讀進要列印的東西, 做適當的處理後,將結果從標準輸出送出。 而這些輸出就會被印出來。請參考過濾程式的運作方式 這一節以更進一步的了解過濾程式。

在我們的印表機設定裡,文字過濾程式可能只是一個執行 /bin/cat 命令的 shell script 將工作送給印表機。 FreeBSD 裡有一個叫做 lpf 的過濾程式能處理倒退、底線等印表機可能無法正確處理的資料。 當然,你也可以任何你想用的過濾程式。關於 lpf 這個過濾程式在 文字過濾程式:lpf 這一節裡有更詳細的說明。

首先,讓我們做一個簡單的 shell script 文字過濾程式, /usr/local/libexec/if-simple。 用你熟悉的編輯器編輯這個檔:

    #!/bin/sh
    #
    # if-simple - Simple text input filter for lpd
    # Installed in /usr/local/libexec/if-simple
    #
    # Simply copies stdin to stdout.  Ignores all filter arguments.
    
    /bin/cat && exit 0
    exit 2

然後要讓這個檔可執行:

    # chmod 555 /usr/local/libexec/if-simple

同時,在 /etc/printcap 設定檔裡用 if 關鍵字告訴 LPD 來使用這個過濾程式。 在下面的例子裡,我們在 /etc/printcap 為兩台印表機都指定了過濾程式:

    #
    #  /etc/printcap for host rose - added text filter
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\
            :if=/usr/local/libexec/if-simple:
    
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :sh:sd=/var/spool/lpd/bamboo:\
            :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:\
            :if=/usr/local/libexec/if-simple:

9.4.2.2.7. 測試

你已經把 LDP 需要的設定都完成了。不過, 我們需要測試看看這些設定是否可以正確的工作。 測試的方法就是印出一些東西。如果要用 LPD 系統來列印,我們可以使用 lpr(1) 這個命令來送出一些列印工作。

你可以使用 檢查印表機連線狀況 這一節裡介紹的 lpr(1)lptest(1) 來產生一些測試文字。

測試 LPD 設定:

輸入:

    # lptest 20 5 | lpr -Pprinter-name

其中 printer-name/etc/printcap 裡的某一台印表機名稱或別名。 如果要測試預設的印表機,那麼在執行 lpr(1) 命令時不要指定 -P 這個參數。再一次的提醒,如果你要測試的是 PostScript 印表機,那麼請傳送 PostScript 程式給印表機,而不要用 lptest(1)。你可以將程式放在一個檔案裡然後輸入 lpr file

如果是 PostScript 印表機,你應該會得到程式輸出的結果。 如果你是用 lptest(1) 的話, 那麼你的結果看起來應該是下面這個樣子:

    !"#$%&'()*+,-./01234
    "#$%&'()*+,-./012345
    #$%&'()*+,-./0123456
    $%&'()*+,-./01234567
    %&'()*+,-./012345678

若要做更進一步的測試,你可以下載更大的程式 (給某個特定印表機語言的印表機使用)或是在執行 lptest(1) 時加一些額外的參數。例如 lptest 80 60 將會產生 60 行每行 80 個字元的測試資料。

如果印表機並沒有反應,請參考 疑難排解這一節。

9.4.2.2.8. 疑難排解

lptest(1) 做過簡單的測試後, 你可能會遇到下列的問題,而不是正確的輸出:

印表機印了一下子,但是並沒有輸出任何結果。

印表機印出上面所列的東西,但是沒多久就停住了。這時, 你可能需要按印表機上的 PRINT REMAINING 或 FORM FEED 鈕才看得到輸出的結果。

如果是這種情況的話, 印表機在列印前可能在等待是否還有更多的資料要列印。 要解決這個問題,你可以讓你的文字過濾程式送出 FORM FEED 字元(或是其他需要的字元)給印表機。 這個動作讓印表機印出目前印表機內暫存區裡的資料。 同時也確定每個工作的最後一頁可以完整的輸出, 使得下個工作不會從前一個工作的最後一頁中間輸出。

下面這個 shell script 取代 /usr/local/libexec/if-simple。 將工作送給印表機後,會再送出一個 form feed 字元:

    #!/bin/sh
    #
    # if-simple - Simple text input filter for lpd
    # Installed in /usr/local/libexec/if-simple
    #
    # Simply copies stdin to stdout.  Ignores all filter arguments.
    # Writes a form feed character (\f) after printing job.
    
    /bin/cat && printf "\f" && exit 0
    exit 2
印出了 ``階梯效應''。

你的結果可能是這個樣子:

    !"#$%&'()*+,-./01234
                                "#$%&'()*+,-./012345
                                                             #$%&'()*+,-./0123456

這時你已經成為因為換行字元衝突而產生的 階梯效應犧牲者。UNIX 風格的作業系統只使用 ASCII 碼 10,line feed (LF) 做為換行字元。MS-DOS、OS/2 以及其他的作業系統使用兩個字元 ASCII 碼 10 以及 ASCII 碼 13 (稱做 carriage return 或 CR)。很多印表機使用 MS-DOS 的表示法來代表換行字元。

當你用 FreeBSD 列印時,你的文件只用 line feed 字元換行。 當印表機看到一個 line feed 字元時,將紙捲了一行, 仍然從同一個位置繼續往後印。這就是為什麼要用 carriage return 字元的原因:將下一個字的列印位置移到紙張的最左邊。

FreeBSD 希望你的印表機可以:

印表機收到 CR印表機列印 CR
印表機收到 LF印表機列印 CR + LF

有一些方法可以達到這個目地:

  • 用印表機上的開關或控制面板設定這些字元的處理方式。 請查閱你的印表機手冊並做正確的設定。

    Note: 如果你的電腦安裝了除了 FreeBSD 之外的作業系統, 你也許得常常重新設定印表機處理 CR 和 LF 的設定。 因此,你可能會較希望使用下面其中之一的方法:

  • 讓 FreeBSD 的序列埠驅動程式自動將 LF 轉換成 CR+LF。 當然,你的印表機只能將在序列埠上。 若要開啟這個功能,只要在 /etc/printcap 設定檔裡為你的印表機用 fs 關鍵字設定 CRMOD 這個位元即可。

  • 送一個 控制碼 給印表機告訴他暫時把 LF 字元做額外的處理。 請參閱你的印表機手冊以了解你的印表機是否支援此功能。 如果你找到適用的控制碼, 修改你的文字過濾程式先送出這些控制碼, 再送出要列印的工作。

    下面這個文字過濾程式的範例是使用 Hewlett-Packard PCL 控制碼。先讓印表機將 LF 視為 LF 和 CR 處理, 再送出工作。最後,再送出將整頁送出的控制碼。 這個過濾程式應該可以應付大部份 Hewlett-Packard 的印表機。

        #!/bin/sh
        #
        # hpif - Simple text input filter for lpd for HP-PCL based printers
        # Installed in /usr/local/libexec/hpif
        #
        # Simply copies stdin to stdout.  Ignores all filter arguments.
        # Tells printer to treat LF as CR+LF.  Ejects the page when done.
        
        printf "\033&k2G" && cat && printf "\033&l0H" && exit 0
        exit 2

    而下面這個 /etc/printcap 的範例是設定一台叫做 orchid 電腦。 他在第一個並列埠連接了一台叫做 teak 的 Hewlett-Packard LaserJet 3Si 印表機。 同時,他使用了上述的 script 做為他的文字過濾程式:

        #
        #  /etc/printcap for host orchid
        #
        teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
                :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\
                :if=/usr/local/libexec/hpif:
每一行都重疊在一起

印表機從不換行,把每一行都印在同一行上。

這個問題和上述的階梯效應``相反''。 而且也較罕見。FreeBSD 用來換行的 LF 字元被當成 CR 字元使得印表機一直回到紙張的最左邊開始列印但卻不換行。

使用印表機上的設定開關或是控制面板設定使 LF 和 CR 字元這樣被處理:

印表機收到印表機列印
CRCR
LFCR + LF

印表機會少印某些字

列印時,印表機在一行之中會少印某些字。 這個情況在列印時可能會變得愈來愈嚴重, 有愈來愈多的字印不出來。

這是因為 印表機收資料的速度無法跟上電腦透過序列埠送資料的速度 (這個問題在並列埠印表機上應該不會發生)。 有兩種方式可以解決這個問題:

  • 如果印表機支援 XON/XOFF 流量控制,在 FreeBSD 裡可以用 fs 關鍵字來設定 TANDEM 位元。

  • 如果印表機支援 carrier 流量控制,用 fs 關鍵字來設定 MDMBUF 位元。 確定連接印表機及電腦的連接線可以配合 carrier 流量控制使用。

  • 如果印表機不支援任何一種流量控制,那麼在 fs 關鍵字裡試著設定 NLDELAY、 TBDELAY、CRDELAY、VTDELAY 以及 BSDELAY 等位元的組合以適當的延遲資料送到印表機。

印出亂碼

印表機印出看不懂的符號,而不是我們期望中的資料。

這通常是因為序列印表機的通訊參數設定不正確而造成的。 再檢查一次 br 關鍵字所設定的傳輸速率、 fsfc 關鍵字所設定的同位元檢查。同時也檢查印表機是否也使用與 /etc/printcap 檔裡相同的設定。

沒有任何動作發生

如果沒有任何反應,那麼可能是 FreeBSD 的問題而不是硬體的問題。為你的印表機在 /etc/printcap 設定檔裡設定紀錄檔 (使用 lf 關鍵字)。 下面的例子是用 lfrattan 這台印表機設定紀錄檔:

    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :sh:sd=/var/spool/lpd/rattan:\
            :lp=/dev/lpt0:\
            :if=/usr/local/libexec/if-simple:\
            :lf=/var/log/rattan.log

然後試著再列印一次,並檢查紀錄檔(在我們的例子裡,是 /var/log/rattan.log 這個檔)裡是否有出現錯誤訊息。 然後根據錯誤訊息來解決你的問題。

如果你沒有用 lf 指定紀錄檔,LPD 預設是 /dev/console 將錯誤訊息輸出。