За достъп до принтера на Windows машина вие трябва да направите следното:
Записа във файла /etc/printcap
показан по-долу е направена за
принтера HP 5MP нa сървър Windows NT. Използват се следните полета на файла
/etc/printcap
:
cm - коментарий lp -име на устройството, отворено за въвеждане sd - директория на спунла на принтера (на локалната машина) af - файл за отчет за използването на принтера mx - максмалнияй разер мна файл (науль --без ограничений) if - име на входния филтър (скрипта)
За по-детайлна информация по повод печатането гледайтете Printing HOWTO или спраoчните страници на printcap.
# /etc/printcap
#
# //zimmerman/oreilly via smbprint
#
lp:\
:cm=HP 5MP Postscript OReilly on zimmerman:\
:lp=/dev/lp1:\
:sd=/var/spool/lpd/lp:\
:af=/var/spool/lpd/lp/acct:\
:mx#0:\
:if=/usr/bin/smbprint:
Убедете се, че буферните директории и директорията използвана за отчет за
ползването, съществуват и са с права за запис. Убедете се, че реда 'if' съдържа правилния
път към скрипта smbprint
(даден по-долу) и
убедете се, че записите сочат към правилното устройство за въвеждане
(специалния файл /dev).
По-нататък е самия скрипт smbprint
. Той обикновенон се намира в директорията
/usr/bin и е написан от Andrew Tridgell, човека, който създаде
Samba, доколкото знам. Този скрипт се намира в пакета с изходния код на Samba,
но осъства в някои бинарни дистрибутиви, така че аз го пресъздадох тук.
Вие може да поискате да погледнете на него по-внимателно. Има някой малки изменения, които се оказаха полезни.
#!/bin/sh -x
# Този скрипт се явява входен филтър за основаната на printcap
# печат на unix-машини. Той използва програмата smbclient за
# печат на файла на посочения smb-сървър и сервиз.
# Например вие можете да имате запис в printcap подобна на тази
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# която създава unix-принтер наречен "smb", който ще
# печата с помоща на този скрипт. На вас ви е необходимо да създадете директория
# на спула /usr/spool/smb със съответстващи права и притежател
# Сложете тук сървър и сервиз на, които искате да печатате.В този
# пример аз имам PC с WfWg PC, наречена "lapland", която има
# експортируем принтер, наричан "printer" без парола
#
# По-нататък скрипта беше променен от [email protected] (Michael Hamilton)
# така, че сървъра, сервиза и паролата могат да бъдат преписани от файла
# /usr/var/spool/lpd/PRINTNAME/.config
#
# За да заработи това записа в /etc/printcap трябва да
# включва файл за отчитане на използването (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:
#
# Файл /usr/var/spool/lpd/PRINTNAME/.config трябва да съдържа
# server=PC_SERVER
# service=PR_SHARENAME
# password="password"
#
# Например,
# server=PAULS_PC
# service=CJET_371
# password=""
#
# Debugging log file, change to /dev/null if you like.
#
logfile=/tmp/smb-print.log
# logfile=/dev/null
#
# The last parameter to the filter is the accounting file name.
#
spool_dir=/var/spool/lpd/lp
config_file=$spool_dir/.config
# Should read the following variables set in the config file:
# server
# service
# password
# user
eval `cat $config_file`
#
# Some debugging help, change the >> to > if you want to same space.
#
echo "server $server, service $service" >> $logfile
(
# NOTE You may wish to add the line `echo translate' if you want automatic
# CR/LF translation when printing.
echo translate
echo "print -"
cat
) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $logfile
Повече от диструбутивите на Linux се доставя с програмата
nenscript
за преобразуване на ASCII документи в
Postscript. Следващия скрипт на perl прави живота на потребителя по-лесен,
осигурявайки прост интерфейс за печатане използвайки smbprint.
Използване: print [-a|c|p] <filename> -a печата <filename> каот ASCII -c печата <filename> отформатиран като изходен код -p печата <filename> като Postscript Ако не са зададени опции, програмата ще се пробва да определи типа на файла и вида на печат съответно
Използвайки smbprint за печатане на ASCII файлове, скрипта следи за дълги редове. Ако е възможно, този скрипт разделя дългия редприа интервала (вместо по средата на думата).
Форматирането на изходния код се изпълнява с помоща на програмата
nenscript
. Тя взима ASCII-файл го форматира в 2 колонки със
заглавие (дата, името на файла и т.н.). Тази програма също така номерира
редовете. Използвайки този скрипт като пример, могат да бъдат добавени
други видове форматиране.
Postscript-документите се явяват вече отформатирани, така че те се печатат веднага.
#!/usr/bin/perl
# Скрипт: print
# Автори: Brad Marshall, David Wood
# Plugged In Communications
# Дата: 960808
#
# Използва се за печатане на сервиза oreilly, който е разположен на
# сървъра zimmerman
# Назначение: Взима файлове от различни типове като аргумент и ги обработва
# съответно за предаване на скрипта за печатане Samba.
#
# В настоящия момент се поддържат типове файлове:
#
# ASCII - Ако дължината на реда е по-дълга от $line_length символи, то
# пренася реда при интервала
# Postscript - Взима без обработка
# Code - Форматира в Postscript (използвайки nenscript), за да
# изобразява правилно (албумен формат, фонт и т.н.)
#
# Определяне на максималната дължина на реда в ASCII текст
$line_length = 76;
# Определяне на пътя към скрипта за печат Samba
$print_prog = "/usr/bin/smbprint";
# Определяне на пътя и името на nenscript (конвертора на ASCII-->Postscript)
$nenscript = "/usr/bin/nenscript";
unless ( -f $print_prog ) {
die "Can't find $print_prog!";
}
unless ( -f $nenscript ) {
die "Can't find $nenscript!";
}
&ParseCmdLine(@ARGV);
# DBG
print "filetype is $filetype\n";
if ($filetype eq "ASCII") {
&wrap($line_length);
} elsif ($filetype eq "code") {
&codeformat;
} elsif ($filetype eq "ps") {
&createarray;
} else {
print "Sorry..no known file type.\n";
exit 0;
}
# Pipe the array to smbprint
open(PRINTER, "|$print_prog") || die "Can't open $print_prog: $!\n";
foreach $line (@newlines) {
print PRINTER $line;
}
# Send an extra linefeed in case a file has an incomplete last line.
print PRINTER "\n";
close(PRINTER);
print "Completed\n";
exit 0;
# --------------------------------------------------- #
# Everything below here is a subroutine #
# --------------------------------------------------- #
sub ParseCmdLine {
# Parses the command line, finding out what file type the file is
# Gets $arg and $file to be the arguments (if the exists)
# and the filename
if ($#_ < 0) {
&usage;
}
# DBG
# foreach $element (@_) {
# print "*$element* \n";
# }
$arg = shift(@_);
if ($arg =~ /\-./) {
$cmd = $arg;
# DBG
# print "\$cmd found.\n";
$file = shift(@_);
} else {
$file = $arg;
}
# Defining the file type
unless ($cmd) {
# We have no arguments
if ($file =~ /\.ps$/) {
$filetype = "ps";
} elsif ($file =~ /\.java$|\.c$|\.h$|\.pl$|\.sh$|\.csh$|\.m4$|\.inc$|\.html$|\.htm$/) {
$filetype = "code";
} else {
$filetype = "ASCII";
}
# Process $file for what type is it and return $filetype
} else {
# We have what type it is in $arg
if ($cmd =~ /^-p$/) {
$filetype = "ps";
} elsif ($cmd =~ /^-c$/) {
$filetype = "code";
} elsif ($cmd =~ /^-a$/) {
$filetype = "ASCII"
}
}
}
sub usage {
print "
Използване: print [-a|c|p] <filename>
-a печата <filename> коот ASCII
-c печата <filename> отформатиран като изходен код
-p печата <filename> като Postscript
Ако не са зададени опции, програмата ще се пробва да
определи типа на файла и вида на печат съответно\n
";
exit(0);
}
sub wrap {
# Create an array of file lines, where each line is < the
# number of characters specified, and wrapped only on whitespace
# Get the number of characters to limit the line to.
$limit = pop(@_);
# DBG
#print "Entering subroutine wrap\n";
#print "The line length limit is $limit\n";
# Read in the file, parse and put into an array.
open(FILE, "<$file") || die "Can't open $file: $!\n";
while(<FILE>) {
$line = $_;
# DBG
#print "The line is:\n$line\n";
# Wrap the line if it is over the limit.
while ( length($line) > $limit ) {
# DBG
#print "Wrapping...";
# Get the first $limit +1 characters.
$part = substr($line,0,$limit +1);
# DBG
#print "The partial line is:\n$part\n";
# Check to see if the last character is a space.
$last_char = substr($part,-1, 1);
if ( " " eq $last_char ) {
# If it is, print the rest.
# DBG
#print "The last character was a space\n";
substr($line,0,$limit + 1) = "";
substr($part,-1,1) = "";
push(@newlines,"$part\n");
} else {
# If it is not, find the last space in the
# sub-line and print up to there.
# DBG
#print "The last character was not a space\n";
# Remove the character past $limit
substr($part,-1,1) = "";
# Reverse the line to make it easy to find
# the last space.
$revpart = reverse($part);
$index = index($revpart," ");
if ( $index > 0 ) {
substr($line,0,$limit-$index) = "";
push(@newlines,substr($part,0,$limit-$index)
. "\n");
} else {
# There was no space in the line, so
# print it up to $limit.
substr($line,0,$limit) = "";
push(@newlines,substr($part,0,$limit)
. "\n");
}
}
}
push(@newlines,$line);
}
close(FILE);
}
sub codeformat {
# Call subroutine wrap then filter through nenscript
&wrap($line_length);
# Pipe the results through nenscript to create a Postscript
# file that adheres to some decent format for printing
# source code (landscape, Courier font, line numbers).
# Print this to a temporary file first.
$tmpfile = "/tmp/nenscript$$";
open(FILE, "|$nenscript -2G -i$file -N -p$tmpfile -r") ||
die "Can't open nenscript: $!\n";
foreach $line (@newlines) {
print FILE $line;
}
close(FILE);
# Read the temporary file back into an array so it can be
# passed to the Samba print script.
@newlines = ("");
open(FILE, "<$tmpfile") || die "Can't open $file: $!\n";
while(<FILE>) {
push(@newlines,$_);
}
close(FILE);
system("rm $tmpfile");
}
sub createarray {
# Create the array for postscript
open(FILE, "<$file") || die "Can't open $file: $!\n";
while(<FILE>) {
push(@newlines,$_);
}
close(FILE);
}
Сега за използването на MagiFilter. Благодаря на Alberto Menegazzi ( [email protected] ) за неговата информация
Alberto съобщи:
--------------------------%<-----------------------------
1) Инсталирайте MagicFilter в /usr/bin/loаclфилтрите за необходимите принтери, но не запълвайте записа в в /etc/princap, както се предполага в документацията на MagicFilter.
2) Запишете в /etc/printcapпримерно ето такъв запис ( Това е направено за моя принтер LaserJet 4L):
lp|ljet4l:\ :cm=HP LaserJet 4L:\ :lp=/dev/null:\ # or /dev/lp1 :sd=/var/spool/lpd/ljet4l:\ :af=/var/spool/lpd/ljet4l/acct:\ :sh:mx#0:\ :if=/usr/local/bin/main-filter:
Вие трябва да обясните, че устройството lp=/dev/... се отваря за блокиране, така че за всеки отдалечен принтер се използва едно "виртуално устройство".
Пример за създаване: touch /dev/ljet4l
3) Напишите филтър /usr/local/bin/main-filter, със същия образ предполагайки използване на ljet4l-filter вместо cat.
Ето как е за мен.
#! /bin/sh logfile=/var/log/smb-print.log spool_dir=/var/spool/lpd/ljet4l ( echo "print -" /usr/local/bin/ljet4l-filter ) | /usr/bin/smbclient "\\\\SHIR\\HPLJ4" -N -P >> $logfile
P.S.: Това е цитт от Print2Win mini-Howto за блокирането, а също така за това, защо да се създават виртуални принтери.
--Начало тук---------
Съвет от Rick Bressler:
Хубав съвет. Аз използвам нещо подобно. Ето един полезен съвет макар и да не се явява хубава идея:
:lp=/dev/null:\
lpr прави 'монополно (exclusive)' отваряне на файла, който вие ще посочите в полето lp=. Той прави това за да предотврати опитите за множество процеси да се печатат едновременно на един и същ принтер. Страничен ефект на това, във вашия случаи се явява това, че eng и colour не могат да печатат едновременно, (обикновенно малко или повече прозрачно, доколкото те вероятно печатат бързо и доколкото вие не забелязвате, че те поставят заданията в ред), но всички други процеси, които се опитват да пишат в /dev/null няма да работят !
На едно потребителска система, това вероятно не се явява голям проблем. При мен има система с 50 принтера. В този случай това може да бъде проблем.
Решението на този проблем се заключаваше в създаването на устройства за всеки тяхен принтер. Например: touch /dev/eng.
Аз модифицирах записа на lp във файла printcap, показан по-горе, взимайки в предвид пожеланията на Rick. Аз направих следното:
#touch /dev/eng #touch /dev/color
---Край -----
--------------------------%<----------------------------------
-