Samba로 PDF 서비스하기

By John Bright

한글번역 전정호

이 글은 한글번역판입니다. 원문은 여기에서 볼 수 있습니다.


소개

PDF 문서는 인터넷에서 문서를 전달하는 좋은 방법이다. 인용문이나 명함을 보내는 등 여러 용도로 사용할 수 있다. PDF 형식이 이렇게 대중적인 두가지 주된 이유는 문서의 형식이 정확히 유지되고 거의 모든 플래폼에서 쉽게 볼 수 있기 때문이다. 윈도우에 갇힌 많은 컴퓨터 사용자에게 PDF 문서를 만드는 것은 금쪽같은 돈이 Adobe로 흘러감을 의미한다. 그러나 이 글은 Linux, Samba, Ghostscript를 사용하여, 윈도우와 리눅스 사용자 모두에게 PDF를 만드는 서비스를 제공하는 방법을 다룬다. 물론 모두 공짜로 얻을 수 있다.

먼저 작업 전체를 살펴보자. 먼저, 우리는 Samba를 사용하여 (사용자에게 보통 프린터처럼 보이는) "가상 프린터" 서비스를 제공한다. Ghostscript는 이 포스트스크립트 프린터의 작업을 PDF 문서로 만든다. 마지막으로 윈도우가 이 공유 프린터를 사용하도록 설정한후, 작업을 포스트스크립트 형식으로 보낸다.

Samba

Samba는 Linux/UNIX에서 윈도우 머쉰과 파일과 프린터를 공유하는 훌륭한 소프트웨어이다. Samba는 윈도우 95/98/NT 등에서 제공하는 표준 "Windows Networking" 서비스와 호환된다. 작업을 위해 Samba를 설정하기 전에 Samba가 리눅스에 설치되있는지 확인해봐라. www.samba.org에서 Samba 소스를 받을 수 있지만, Debian, Red Hat 등이 제공하는 "samba" 패키지로 쉽게 설치할 수 있다.

처음 Samba를 설치해본다면 (/etc나 /etc/samba에 있는) smb.conf의 기본 설정 옵션을 살펴보고 수정할 필요가 있다. 서비스를 시작하기위해 주로 살펴볼 것은 보안 정책(security=share 혹은 security=user)과 "guest account" 설정이다. Samba를 설정에 대한 자세한 내용은 www.samba.org의 Samba 문서나 SMB HOWTO를 참고하라. (보안정도는 낮은) 완전한 설정파일 예가 아래 나온다.

간단한 파일공유를 만들어서 연결과 (있다면) 인증방법을 검사해보길 바란다. 클라이언트가 Samba 서버에 접속이 가능하다면, 이제 PDF "가상 프린터"를 만들 차례다. 그러나 먼저 실제 PDF 문서를 만들기위한 도구가 있는지 확인해 보자.

Ghostscript

Ghostscript도 리눅스에서 사용할 수 있는 훌륭한 프로그램이다. Ghostscript는 보통 포스트스크립트를 프린터에 적합한 형식으로 변경하는데 사용하지만, 포스트스크립트와 PDF 형식간의 변환도 가능하다. Ghostscript는 많은 배포본에서 프린터 지원을 위해 설치된다. "gs" 명령어가 시스템에 있다면 Ghostscript는 이미 설치되었을 것이다. 없다면 배포본 패키지(Red Hat에서 ghostscript, Debian에서 gs나 gs-aladdin)나 모험을 좋아한다면 http://www.cs.wisc.edu/~ghost/에서 소스를 받아서 설치할 수 있다.

Ghostscript 패키지에서 포스트스크립트를 PDF로 쉽게 변환하는 ps2pdf라는 스크립트를 찾을 수 있다. 이제 이 도구가 있다면 Samba에 PDF 서비스를 만들어보자.

한데 모으기

먼저 (smb.conf 파일에서) Samba의 전형적인 기본프린터 공유를 살펴보자.

[hpdeskjet]
	path = /tmp
	printable = yes
	writeable = no
	create mask = 0700
	guest ok = yes
	printer name = lp

(writeable에서 "e"를 주의하라. 보통 단어와 달리 설정파일에서는 "e"가 있다. 이는 아래 browseable에도 적용된다. 실제로 Samba에서 두가지 다 가능하지만, Samba manpage는 writeable을 사용한다.)

보통 프린터 작업이 이 공유에 스풀될때 작업을 리눅스 프린팅 시스템으로 옮기기위해 lpr과 같은 명령어가 실행된다. 여기서 우리는 lpr 대신 다른 프린트 명령어를 지정하기 위해서 Samba의 설정을 바꾼다. 정확한 설정변수는 "print command"이다. 지정한 명령어가 실행될때 "print command" 변수에서 %f나 %s는 원도우 클라이언트가 보낸 프린터 스풀 파일명으로 대체된다. 예를 들어 프린터 작업을 그냥 무시하려면, 위의 프린터 설정을 다음과 같이 바꾼다.

	print command = /bin/rm %f
여기서 주의할 점이 있다. 어떤 작업을 지정하던지 스풀 파일을 반드시 지워야 한다. 지우지 않으면 파일들이 결국 디스크를 다 차지하게 된다.

프린트 스크립트

프린트 스크립트는 포스트스크립트 형식의 프린터 스풀 파일명을 명령행 아규먼트로 받는다. 이 파일을 PDF 문서로 변환한후 접근할 수 있는 곳에 둘 것이다. 클라이언트는 Samba의 파일 공유 서비스를 이용하여 완성된 결과를 얻을 수 있다. 예를 들어 Samba가 "/shr"라는 디렉토리를 공유한다면 완성된 PDF 문서를 /shr/pdfropbox/안에 둘 수 있다. 선택한 디렉토리를 만들어라(mkdir). 또, PDF 파일을 만들기위해 Samba 사용자(이 예제에서는 nobody)에게 디렉토리의 쓰기 권한을 줘야 한다. 이 예제에서는 다음과 같이 한다.
chown nobody /shr/pdfdropbox
chmod u+rwx /shr/pdfdropbox
printpdf라는 간단한 프린트 스크립트가 여기에 있다. 리눅스에서 이 스크립트를 /usr/bin/printpdf로 옮긴다.

#!/bin/sh

# Simple script to convert a specified postscript file into a PDF document
# and place it in a location that is shared by the Samba server.
# 
# Arguments:
#   1st - The name of the spool file
#
# John Bright, 2001, jbright@winfordeng.com

# We will create the pdf into a temporary file based upon the current date and time.
# After we are finished, we'll rename it to a file with the same date, but ending
# in .pdf.  We do this because if a user tries to open a PDF that is still being written,
# they will get a message that it is corrupt, when it is actually just not done yet.

DATE=`date +%b%d-%H%M%S`

# Directory in which to place the output
# Be sure this directory exists and is writable by the user that Samba
# is running as (for example, the nobody user)
OUTDIR=/shr/pdfdropbox

ps2pdf $1 $OUTDIR/$DATE.temp
mv $OUTDIR/$DATE.temp $OUTDIR/$DATE.pdf
rm $1

(역주; 한글로 된 파일명에 문제가 있다면, DATE=`LC_ALL=C date +%b%d-%H%M%S`와 같이 스크립트를 수정하라.) 진짜 간단하다. 이제 필요한 도구를 모두 준비했다.

Samba 설정 끝내기

이제 Samba 설정을 마치자. 다음은 동작하는 예제 smb.conf 파일이다. 보안이 낮지만, 간단하게 만들었다. 여기에서 이 파일을 받을 수 있다.

[global]
   guest account = nobody
   invalid users = root

   ; Tighten security just a little: only allow local access
   interfaces = 127.0.0.1 eth0
   bind interfaces only = Yes
   ; This assumes you are on a local network with 192.168.x.x IP addresses
   hosts allow = 192.168.
   
   ; Share-level security is generally easier, although not as secure
   security=share
   
   workgroup=WORKGROUP

; Set up a public share, this will be used to retrieve PDFs
; The name of the share will be seen as "shr" by Windows users
[shr]
   path = /shr
   browseable = yes
   writeable = yes
   guest ok = yes
   force user = nobody

; Set up our PDF-creation print service
[pdf]
   path = /tmp
   printable = yes
   guest ok = yes
   print command = /usr/bin/printpdf %s
   
   ; There is no need to support listing or removing print jobs,
   ; since the server begins to process them as soon as they arrive.
   ; So, we set the lpq (list queued jobs) and lprm (remove jobs in queue)
   ; commands to be empty.
   lpq command =
   lprm command =

물론 설정파일 smb.conf을 수정한후 Samba를 재시작해야 한다.

윈도우 클라이언트 설정하기

이제 윈도우 클라이언트에 공유 PDF 프린터를 네트웍 프린터로 설치해야 한다. 이를 위해 "네트워크 환경"에서 프린터 공유를 찾은 다음 오른쪽 클릭으로 설치를 선택한다. 설치중에 프린터 드라이버를 물을 것이다. 아무 포스트스크립트 프린터 드라이버를 선택하면 된다. (예를 들어 HP LaserJet 5P/5MP Postscript)

간단히 말해서 리눅스 머쉰의 PDF 서비스는 입력을 포스트스크립트 형식으로 받는다. printpdf 스크립트가 윈도우 클라이언트가 보낸 작업을 그대로 받기때문에 윈도우 클라이언트는 포스트스크립트 형식으로 프린터 작업을 보내야 한다. 그래서 윈도우 클라이언트에 PDF 네트웍 프린터를 선택할때 포스트스크립트 프린터용 드라이버를 선택한 것이다. 나는 일반적으로 윈도우 프린터 드라이버 목록에서 (HP LaserJet 5P/5MP Postscript와 같이) HP Laserjet PS 프린터계열을 선택하지만 마이크로소프트가 제공하는 포스트스크립트 드라이버는 기본적으로 같기때문에 아무것이나 선택해도 된다.

윈도우에 PDF 네트웍 프린터를 설치했다면 어떤 프로그램에서 새로운 네트웍 프린터로 출력하더라도 잠시후 PDF 문서를 얻을 수 있다.

능률적으로

컴퓨터에 익숙하지 않은 사람들이 많은 사무실이라면 설치과정과 적절한 프린터 드라이버를 선택하는 작업이 어려울 수 있다. 다른 윈도우에서 네트웍 프린터를 설치해봤다면, 드라이버를 묻지않고 자동으로 프린터 드라이버가 복사된 것을 봤을지도 모르겠다. Samba로도 이런 일을 할 수 있다. 먼저 리눅스에 (쌍따옴표는 빼고) "printer$"라는 파일 공유를 만든다. printer$ 공유의 경로를 /etc/samba/printdrivers/로 한다. (물론 이 디렉토리를 만들어야 한다.) 클라이언트는 설치중에 프린터 드라이버 파일을 얻기위해 이 공유를 사용한다.

이제 어떤 드라이버 파일을 printer$ 공유 디렉토리에 복사해야할지 알아내야 한다. 또 클라이언트에게 어떤 드라이버 파일이 필요한지를 알려주는 프린터 정의(printer definition)도 만들어야 한다. 고맙게도 make_printerdef 라는 Samba 도구를 사용하면 한번에 해결된다. 이 도구를 사용하려면 프린터를 정의하는 윈도우 INF 파일과 "HP LaserJet 5P/5MP PostScript"와 같은 프린터 이름이 필요하다. 프린터가 정의된 INF 파일이 무엇인지를 알아야한다. 예를 들어, LaserJet은 C:\WINDOWS\INF\MSPRINT3.INF에 정의되있다. C:\WINDOWS\INF가 숨김 디렉토리임을 주의하라. 이 파일을 리눅스에 복사하고, Samba가 읽을 프린터 정의 파일을 만들기위해 make_printerdef를 사용한다. 예를 들어,

make_printerdef MSPRINT3.INF "HP LaserJet 5P/5MP PostScript" >> /etc/samba/printers.def

프린터 설정을 만들기위해 표준출력을 printers.def 파일로 리다이렉트한다. make_printdef 프로그램은 표준오류로도 설명을 출력한다. 이 프로그램은 필요한 드라이버 파일이 무엇인지 알려준다. 이 파일을 C:\WINDOWS\SYSTEM이나 C:\WINDOWS에서 찾을후 리눅스의 printer$ 공유 경로(이 예에서는 /etc/samba/printerdrivers)에 복사해야 한다. 생성한 (아니면 추가한) printers.def 파일은 윈도우와 공유할 필요는 없다. 이 파일은 Samba만이 읽는다. 이제 Samba에게 printers.def 파일과 드라이버 파일에 대해 알려준다. 이는 smb.conf에서 global 섹션의 "printer driver file" 설정과 각 프린터 섹션에서 "printer driver", "printer driver location" 설정으로 가능하다. 다음은 수정한 smb.conf 파일로 printer$ 공유의 예를 보여준다. 여기에서 이 설정파일을 받을 수 있다.

[global]
   guest account = nobody
   invalid users = root

   ; Tighten security just a little: only allow local access
   interfaces = 127.0.0.1 eth0
   bind interfaces only = Yes
   ; This assumes you are on a local network with 192.168.x.x IP addresses
   hosts allow = 192.168.
   
   ; Share-level security is generally easier, although not as secure
   security=share
   
   workgroup=WORKGROUP

   printer driver file = /etc/samba/printers.def
   
; Set up a public share, this will be used to retrieve PDFs
; The name of the share will be seen as "shr" by Windows users
[shr]
   path = /shr
   browseable = yes
   writeable = yes
   guest ok = yes
   force user = nobody

; Set up our PDF-creation print service
[pdf]
   path = /tmp
   printable = yes
   guest ok = yes
   print command = /usr/bin/printpdf %s
   
   ; There is no need to support listing or removing print jobs,
   ; since the server begins to process them as soon as they arrive.
   ; So, we set the lpq (list queued jobs) and lprm (remove jobs in queue)
   ; commands to be empty.
   lpq command =
   lprm command =
   
   ; We already defined the printer driver definition file above.
   ; Here we need to specify the entry in that file that should be used
   ; for this printer.
   printer driver = HP LaserJet 5P/5MP PostScript
   printer driver location = \\%h\printer$

; File share to allow clients to download printer drivers
[printer$]
   path = /etc/samba/printdrivers
   guest ok = yes
   read only = yes
   

리눅스 클라이언트 설정하기

이 부분은 윈도우 클라이언트에 PDF 서비스를 제공하는데는 필요없다. 리눅스 클라이언트에서 PDF 서비스를 사용하는 방법을 설명한다. 리눅스 클라이언트에서 필요한 도구를 더 쉽게 설치할 수 있기 때문에 이 서비스는 아마 그렇게 유용하지는 않을 것이다. 그러나 중앙화된 PDF 생성 서비스를 만드는데는 유용하다. (주: 윈도우에도 Ghostscript가 있지만, 대부분 사용자에게는 여기서 설명한 프린터 서비스 기반의 방법보다 어려울 것이다.) 또, PDF 서비스로 프린트하는 방법은 Samba나 윈도우의 다른 프린터 서비스에 프린트하는데도 사용할 수 있기때문에, 이 방법을 다룬다. (역주; RedHat과 Debian 모두 이미 윈도우 공유 프린터로 프린트하는 배포본 특유의 방법이 있다. 아래 방법을 사용하면, 그래픽 환경에서 설정한 프린터와 호환이 안될 수 있다. 배포본 특유의 방법은 해당 배포본 문서를 참고하라.)

리눅스에서 윈도우 프린터 공유에 프린트하는 방법은 많다. 아마도 가장 좋은 방법은 /etc/printcap에 필터로 (smbclient를 사용하는) smbprint 스크립트를 사용하는 것이다. 이 방법을 사용하면 리눅스 사용자와 프로그램에 익숙한 표준 lpr 명령어로 윈도우 공유 프린터에 프린트할 수 있다. 컴퓨터에 smbprint와 smbclient 프로그램이 있는지 확인하라. smbclient 프로그램은 Debian의 "smbclient" 패키지와 Red Hat의 "samba-client" 패키지에서 찾을 수 있다. Red Hat에서 smbprint 스크립트는 "samba-client" 패키지에 포함되있다. Debian에서는 "samba-doc" 패키지와 "printfilters-ppd", "lprngtool" 패키지에 서로 다른 버전이 있다. 서로 다른 많은 버전들이 있어서 여기에 있는 것을 복사하는 편이 낫다. 여기에서 받을 수 있다. 이제 /usr/bin/smbprint에 smbprint가 있고 실행가능하다고 (chmod +x /usr/bin/smbprint) 가정한다. 다음은 smbprint 스크립트이다.

#!/bin/sh
# This script is an input filter for printcap printing on a UNIX machine. It
# uses the smbclient program to print the file to the specified smb-based 
# server and service.
# For example you could have a printcap entry like this
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# which would create a UNIX printer called "smb" that will print via this 
# script. You will need to create the spool directory /usr/spool/smb with
# appropriate permissions and ownerships for your system.

# Set these to the server and service you wish to print to 
# In this example I have a Windows for Workgroups PC called "lapland" that has
# a printer exported called "printer" with no password.

#
# Script further altered by hamiltom@ecnz.co.nz (Michael Hamilton)
# so that the server, service, and password can be read from 
# a /usr/var/spool/lpd/PRINTNAME/.config file.
#
# In order for this to work the /etc/printcap entry must include an 
# accounting file (af=...):
#
#   cdcolour:\
#	:cm=CD IBM Colorjet on 6th:\
#	:sd=/var/spool/lpd/cdcolour:\
#	:af=/var/spool/lpd/cdcolour/acct:\
#	:if=/usr/local/etc/smbprint:\
#	:mx=0:\
#	:lp=/dev/null:
#
# The /usr/var/spool/lpd/PRINTNAME/.config file should contain:
#   share=PC_SERVER
#   user="user"
#   password="password"
#
# Please, do not modify the order in the file.
# Example:
#   share=\\server\deskjet
#   user="fred"
#   password=""

#
# The last parameter to the filter is the accounting file name.
#   Extract the directory name from the file name.
#   Concatenate this with /.config to get the config file.
#
eval acct_file=\$$#
spool_dir=`dirname $acct_file` 
config_file=$spool_dir/.config

# Should read the following variables set in the config file:
#   share
#   hostip
#   user
#   password

eval `cat $config_file`

share=`echo $share | sed "s/[\]/\//g"`

if [ "$user" != "" ]; then
   usercmd="-U"
else
   usercmd=""
fi

if [ "$workgroup" != "" ]; then
   workgroupcmd="-W"
else
   workgroupcmd=""
fi

if [ "$translate" = "yes" ]; then
 command="translate ; print -"
else
 command="print -"
fi
#echo $share $password $translate $x_command > /tmp/smbprint.log

cat | /usr/bin/smbclient "$share" "$password" -E ${hostip:+-I} \
     $hostip -N -P $usercmd "$user" $workgroupcmd "$workgroup" \
     -c "$command" 2>/dev/null

다음은 /etc/printcap에 새로운 항목을 추가하고 smbprint 스크립트를 필터로 지정하는 일이다. 여기 printcap 항목의 예가 있다. 여기에서 받을 수 있다.

# PDF Service entry

lp|pdf|PDF Printer:\
        :lp=/dev/null:sh:\
        :sd=/var/spool/lpd/pdf:\
        :af=/var/spool/lpd/pdf/acct:\
        :mx#0:sh:\
        :if=/usr/bin/smbprint:

스풀 디렉토리 /var/spool/lpd/pdf/를 만들어라. (혹은 LPRng를 사용한다면, checkpc -f를 실행하라.) printcap 항목에 어카운트 파일 줄(af=...)을 확인하라. smbprint 스크립트가 .config 파일을 찾기위해서 어카운트 파일이 .config 파일과 같은 디렉토리에 있어야 한다. 또 기본 프린터명인 "lp"를 사용하였다. 만약 이미 /etc/printcap 파일이 있고 기존의 기본 프린터를 유지한다면, 위에서 앞의 "lp|"를 지워야한다. 다음으로 설정파일 ".config"를 만든다. 이 파일은 /var/spool/lpd/pdf/.config 에 있어야 한다. .config 파일은 프린터 작업을 보낼 서버를 지정한다. 예를 들어,

share=//yourserver/pdf
user=""
password=""

여기서 PDF 서비스를 제공하는 컴퓨터명으로 yourserver를 바꾼다. 동작하지 않으면 혹시 smbprint 스크립트가 .config 파일을 읽을 권한이 있는지 확인해봐라. 최소한 처음에 가장 확실한 방법은 chmod a+r /var/spool/lpd/pdf/.config 와 같이 모두에게 읽기 권한을 주는 방법이다. (역주; .config 파일은 사용자명과 암호가 저장되있기 때문에 조심해야 한다.)

마지막으로 다음과 같이 리눅스에서 포스트스크립트 파일을 PDF 서비스로 프린트할 수 있다.

lpr -Ppdf file_to_print.ps
이 방법은 많은 프로그램에서 사용할 수 있다. 예를 들어, Netscape에서 프린트 명령어로 "lpr -Ppdf"를 사용하면 웹페이지를 PDF 문서로 만들 수 있다.

PDF 문서 보기

마지막으로 다룰 주제는 PDF 문서는 보는 방법이다. 모두들 윈도우에서는 Adobe Acrobat Reader밖에 없다는 것을 알지만, 리눅스에는 선택사항이 많다. 불행히도 윈도우에서만큼 결정적인 것은 없지만 잘 작동한다. 많이 사용되는 것은 다음과 같다.

사견으로 사용자 환경은 gnome-gv가 제일 좋은 것 같다. GTK+를 기반이기 때문에 특별히 신경쓰지않아도 마우스휠 등이 작동한다. 불행히도 못읽는 PDF 문서가 있고, ghostscript가 지저분하게 보이는 오류문을 출력한다. 내 경험상 acroread는 문서를 해석하는데 가장 좋다. 과거에는 프로그램이 죽기도 하였지만 현재 매우 좋아졌다. 나는 gv를 사용하지는 않지만 둘다 ghostscript를 기반으로 하기때문에 gnome-gv과 같은 문제가 있을 것 같다. 마지막으로 xpdf는 매우 안정적이다. 나는 이 프로그램이 죽는 것을 못봤고 문서를 해석하는데도 문제가 없다. 그러나 몇몇 사소한 문제가 있고 기능이 적으며 문서의 출력질이 낮다. 그러나 살펴볼만한 좋은 프로그램이다. 겁을 먹었을지 모르지만 평균적으로 리눅스에서 PDF를 보는 것은 (역주; 적어도 영어권에서) 문제가 없다.

그럼 잘 이용하길 바란다!

John Bright

John Bright는 Winford Engineering의 공동경영자이고 맡은 리눅스 관리와 프로그래밍을 잘 한다. :) 그는 대학에서 많은 리눅스와 유닉스를 관리하며 여러 리눅스관련 프로젝트로 바쁘다.


Copyright © 2001, John Bright.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 72 of Linux Gazette, November 2001