Thursday, April 9, 2009

"We're Linux" Video Finalists

The Linux Foundation has announced the finalists in their "We're Linux" competition. While I consider all the entries rather weak, my favorite is this one:

Project: Building An All-Text Linux Workstation - Part 7

Today, we will finish up with printing by taking a look at the command line tools provided by CUPS.

CUPS supports two different families of printer tools. The first, Berkley or LPD comes from the Berkley Software Distribution (BSD) version of Unix and the second is SysV from the System V version of Unix. Both families include comparable functionality, so choosing one over the other is really a matter of personal taste.

Setting A Default Printer
A printer can be set as the default printer for the system. This will make using the command line print tools easier. To do this we can either use the web-based interface to CUPS at http://localhost:631 or we can use the following command:

lpadmin -d printer_name

where printer_name is the name of a print queue we defined in Part 6 of the series.

Sending A Job To The Printer (Berkley-Style)
The lpr program is used to send a job to the printer. It can accept standard input or file name arguments. One of the neat things about CUPS is that it can accept many kinds of data formats and can (within reason) figure out how to print them. Typical formats include PostScript, PDF, text, and images such as JPEG.

Here we will print a directory listing in three column format to the default printer:

ls /usr/bin | pr -3 | lpr

To use a different printer, append -P printer_name to the lpr command. To see a list of available printers:

lpstat -a

Sending A Job To The Printer (SysV-Style)
The SysV print system uses the lp command to send jobs to the printer. It can be used just as lpr in our earlier example:

ls /usr/bin | pr -3 | lp

however, lp has a different set of options. For example to specify a printer, the -d (for destination) option is used. lp also supports many options for page formatting and printer control not found with the lpr command.

Examining Print Job Status
While a print job is being printed, you may monitor its progress with the lpq command. This will display a list of all the jobs queued for printing. Each print job is assigned a job number that can be used with to control the job.

Terminating Print Jobs
Either the lprm (Berkley) or cancel (SysV) commands can be used to remove a job from a printer queue. While the two commands have different option sets, either command followed by a print job number will terminate the specified job.

Getting Help
The following man pages cover the CUPS printing commands

lp lpr lpq lprm lpstat lpoptions lpadmin cancel lpmove

In addition, CUPS provides excellent documentation of the printing system commands in the help section of the online interface to the CUPS server at:

http://localhost:631/help

Select the "Getting Started" link and the "Command Line Printing And Options" topic.

A Follow Up On Part 4
Midnight Commander allows direct access to its file viewer and built in text editor. The mcview command can be used to view files and the mcedit command can be used to invoke the editor.

Further Reading

Other installments in this series: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Saturday, April 4, 2009

LinuxCommand.org (And Others) Under DDoS Attack

Since Thursday my domain registrar, register.com, has been under heavy distributed denial of service (DDoS) attack. This has, at times, made all or part of LinuxCommand.org unavailable. Here is the latest news:
Dear William,

Earlier today we communicated to you we were experiencing intermittent
service disruptions as a result of a distributed denial of service
(DDoS) attack – an intentionally malicious flooding of our systems
from various points across the internet.

We want to update you on where things stand.

Services have been restored for most of our customers including hosting
and email. However for some of our customers, services are not fully
restored. We know this is unacceptable.

We are using all available means to restore services to every one of
our customers and halt this criminal attack on our business and our
customers’ business. We are working round the clock to make that happen.

We are committed to updating you in as timely manner as possible,
please check your inbox or our website for additional updates.


Thank you for your patience.



Larry Kutscher
Chief Executive Officer
Register.com

Tip: Redirecting Multiple Command Outputs

Let's imagine a simple script:
#!/bin/bash

echo 1
echo 2
echo 3
Simple enough. It produces three lines of output:
1
2
3
Now let's say we wanted to redirect the output of the commands to a file named foo.txt. We could change the script as follows:
#!/bin/bash

F=foo.txt

echo 1 >> $F
echo 2 >> $F
echo 3 >> $F
Again, pretty straightforward, but what if we wanted to pipe the output of all three echo commands into less? We would soon discover that this won't work:
#!/bin/bash

F=foo.txt

echo 1 | less
echo 2 | less
echo 3 | less
This causes less to be executed three times. Not what we want. We want a single instance of less to input the results of all three echo commands. There are four approaches to this:

Make A Separate Script
script1:
#!/bin/bash

echo 1
echo 2
echo 3
script2:
#!/bin/bash

script1 | less
By running script2, script1 is also executed and its output is piped into less. This works but it's a little clumsy.

Write A Shell Function
We could take the basic idea of the separate script and incorporate it into a single script by making script1 into a shell function:
#!/bin/bash

# shell function
run_echoes () {
echo 1
echo 2
echo 3
}

# call shell function and redirect
run_echoes | less
This works too, but it's not the simplest way to do it.

Make A List
We could construct a compound command using {} characters to enclose a list of commands:
#!/bin/bash

{ echo 1; echo 2; echo 3; } | less
The {} characters allow us to group the three commands into a single output stream. Note that the spaces between the {} and the commands, as well as the trailing semicolon after the third echo, are required.

Launch A Subshell
Finally, we could do this:
#!/bin/bash

(echo 1; echo 2; echo 3) | less
Placing the list inside () creates a subshell, or another copy of bash and it executes the commands. This has the same result as enclosing the list of commands within {} but with more overhead. The real reason we would want to do this is if, instead of just redirecting the output, we wanted to put all three commands in the background:
#!/bin/bash

(echo 1; echo 2; echo 3) > foo.txt &
This doesn't make much sense for our echo commands (they execute too quickly to bother with), but if we have commands that take a long time to run, this technique can come in handy.

Enjoy!