Stopping Is One Command; Starting Again Is the Hard Part
Xi-Text has a genuine bulk operation. Every command in the spstart family takes the printer name as a pattern, so sphalt -f '*' halts every printer on the host in one step, and spstart -f '*' starts them again. Hand-written loops over a printer list are unnecessary.
Read this before planning a maintenance window: stopping is reliable and starting is not automatic. Four things follow a bulk stop, and none of them announces itself.
- Stopping the spooler halts every printer, and starting the spooler again leaves them all halted. When the scheduler reloads the saved printer list it forces every entry to halted, whatever state it was in when the spooler stopped. Printers must be started explicitly after every spooler restart.
- A printer that fails to start reports nothing to the command that started it. The printer is brought up by a separate process the scheduler forks, so spstart succeeds and the printer sits in error. The record is in the system report file.
- Starting everything also starts the printers that were already stopped. spstart -f '*' treats halted, offline and error identically, so a printer that was broken before the window comes back indistinguishable from one halted for it. Capture the printer states before stopping anything.
- Every printer with an alignment file is re-armed by the restart and will print its alignment page and wait for an operator at its first job. Somebody has to answer.
Why Stop All Printers?
- System maintenance windows
- Xi-Text software updates
- Server shutdown or restart
- Hardware maintenance
- Emergency situations
- Network maintenance
- Printer firmware updates
Record the Printer States First
This is the step that makes the restart safe, because it is the only record of which printers were working when the window opened.
splist -H > /var/tmp/printers-before.txt
splist lists every printer with its state and needs no privilege. Its default listing is printer name, device, form type, state, job number and job owner. The -H option adds a column header; without it there is no header line.
The format letters are lower case, and only lower-case letters are defined. The ones used below:
| Letter | Field |
|---|---|
| %p | Printer name |
| %d | Device |
| %f | Form type |
| %s | State, with the printer's feedback message appended after a colon for offline and error |
| %t | State alone, with no feedback message |
| %j | Number of the job being printed |
| %u | Owner of that job |
| %l | Marked local-only |
An undefined letter is passed through as a literal character rather than rejected, so a mistyped format produces that letter repeated once per printer, with no error. Check a new format string against one printer before building anything on it.
splist takes printer names as arguments, and -q takes the same kind of pattern the stop and start commands take, so the listing can be narrowed the same way the action is:
splist -H -q 'inv*,lp[123]'
One difference is worth knowing before using splist as the check on a bulk operation: splist filters by class code and the stop and start commands do not. splist shows the printers whose class code has a bit in common with the caller's, which on a default installation is every printer, and on a site that partitions printers by class code is a subset. sphalt, spstop and spstart apply no such filter, so they can act on printers the same user's splist output leaves out.
Stopping Every Printer
The printer name argument is a pattern, so one command covers the whole host.
Halt at end of job (graceful):
sphalt -f '*'
Each printer finishes the job it is on and then stops. A printer that is idle, or waiting for an operator, stops at once.
Stop immediately (abandon the job in progress):
spstop -f '*'
Interrupt (stop now, and release the job for another printer):
spinter -f '*'
Why -f is needed. When a pattern matches more than one printer, the command refuses to act without it:
12 printers fit the description *.
If you mean all of them re-run sphalt with the -f option.
That refusal is the safety net. Quote the pattern so the shell passes the asterisk through instead of expanding it against the current directory.
The pattern is richer than a plain asterisk. It accepts *, ?, a bracketed character range and comma-separated alternatives, and it matches letters without regard to case, so a subset is one command too:
sphalt -f 'inv*,lp[123]'
What "All Printers" Covers
Every printer defined on this host, in every state. Printers that are already halted, offline or in error are passed over silently and counted as done, so the command is safe to repeat and safe to run on a system that has not been surveyed.
Printers owned by another host are excluded. A bare pattern matches local printers only. Another host's printers are addressed by prefixing the host name, and that requires the remote-printer privilege:
sphalt -f 'server2:*'
Without that privilege the command exits with a permission error. On a network of Xi-Text hosts, quieting every printer means running the command once per host.
There is no bulk operation in spq. The printer screen acts on the printer under the cursor, one at a time. Beyond a handful of printers, the command line is the only practical route.
What Happens to the Job That Is Printing
Work is preserved in every case. The difference between the three commands is how much reprinting the job costs.
| Command | Job in progress | Where it resumes |
|---|---|---|
| sphalt | Finishes normally | Complete; nothing to resume |
| spstop | Abandoned, and released back into the queue | From the page it had reached, less the printer's configured wind-back |
| spinter | Abandoned, and released back into the queue | The same, and the printer immediately looks for another job |
The page reached is recorded on the job as it prints, page by page, so an abandoned job restarts near where it stopped rather than from page one. It keeps its place in priority order in the queue.
The one operation that destroys work is A on the printer screen in spq, which aborts the printing job and deletes it from the queue. None of the three bulk commands does that.
How much has already been sent to the printer's own buffer is outside Xi-Text's control, so an immediate stop reaches the paper only once that buffer drains.
Starting Every Printer Again
spstart -f '*'
This starts every printer that is halted, offline or in error. The three are treated identically, and error is recovered exactly as offline is. Printers that are already running are left alone, and a pending end-of-job halt on a running printer is cancelled.
Success from spstart means the request was accepted, rather than that the printer started. The scheduler forks a separate process to bring the printer up, and that process is what reads the .device file and the form-type setup file, opens the device and sends the setup string. If any of that fails, the printer goes to error and the reason is written to the system report file. Verify with splist rather than by the exit status:
splist -H -F "%p %s"
For one printer, spstat is a scriptable test that sets the exit status. With no state argument it asks whether the printer is running; with a state name it asks whether the printer is in that state.
spstat lp1 # exit 0 if running, 1 if not
spstat lp1 idle # exit 0 if idle
Alignment printers stop for an operator at the first job. A printer whose setup file names an alignment file is armed for alignment every time it starts. The alignment page prints when the printer takes its first job, and the printer then waits for approval. Approve or reject from the command line with spok and spnok, or with y and n on the spq printer screen.
Stopping and Starting the Spooler Itself
A software update or a server restart stops the whole spooler rather than the printers individually.
sstop -y
sstop halts every local printer as its first act, and it does so immediately - the same way spstop does, abandoning the jobs in progress rather than letting them finish. It then shuts down the network connections, writes the queue to disk and releases the shared memory. On a busy system with many printers this can take up to five minutes.
Halt gracefully first where the time can be spared. Running sphalt -f '*' and waiting for the printers to go quiet before sstop -y is the difference between jobs completing and jobs being reprinted.
Without -y, sstop prompts for confirmation on standard input, so a script that omits it hangs.
Starting the spooler again:
spstart 2000 50
The two numbers are the initial job and printer allocations. Then - and this is the step that gets missed - start the printers:
spstart -f '*'
Nothing about the printers' running state survives a spooler restart. Reading the saved printer list sets every entry to halted and clears the pending-halt and alignment flags. What does survive is the printers' configuration: names, devices, form types, class codes, size limits and descriptions are all held in that saved list.
Suspending Scheduling Instead of Stopping Printers
For a short window where the printers themselves are fine, suspending scheduling stops the spooler handing out new work while leaving everything running.
ssuspend -y 3600
srelease
The argument is a number of seconds. srelease takes no arguments and clears the suspension.
Four things to know before relying on it:
- Without -y it prompts for confirmation, so a script must supply it.
- It suspends the assignment of queued jobs to printers. Users can still submit work with spr; the queue simply grows.
- Nothing displays that scheduling is suspended. Neither splist nor spq shows it. The symptom is printers sitting idle with jobs queued and no visible reason, which is easily mistaken for a fault.
- It is cleared by a spooler restart, so a suspension left in place ends at the next sstop and spstart cycle rather than persisting.
Give the time as an argument rather than answering the prompt: a value entered at the prompt above two hours is silently replaced by five minutes.
Using spq
spq is the right tool for a handful of printers and the wrong one for fifty.
- Press o to switch to the printer section, or start with spq -p to open on it.
- Move the cursor to a printer.
- Press h to halt at the end of the current job, or H to stop immediately.
- Press G to start a stopped printer, or to cancel a pending end-of-job halt.
- Repeat for each printer - no key acts on all of them.
Note that h is the gentle one and H the abrupt one, which is the reverse of the usual convention.
A Maintenance Window, Start to Finish
The whole procedure is short enough to run by hand, which is safer than a script for an operation of this consequence. Every command below works on each platform Xi-Text ships on.
1. Record the starting position.
splist -H > /var/tmp/printers-before.txt
2. Stop new work being handed out.
ssuspend -y 3600
3. Halt the printers gracefully and let the jobs in progress finish.
sphalt -f '*'
4. Wait, and check. Repeat until nothing is printing.
splist -H -F "%p %s %j"
5. Do the maintenance. If it requires the spooler down, run sstop -y now and spstart 2000 50 afterwards.
6. Start the printers. Required after a spooler restart, and harmless if the spooler stayed up.
spstart -f '*'
7. Compare against the record and investigate anything that differs.
splist -H
8. Release scheduling.
srelease
9. Watch the first few jobs through, and answer the alignment prompt on any printer that uses one.
Emergency Stop
To stop everything now, accepting that the jobs in progress will be reprinted:
spstop -f '*'
The jobs return to the queue, so restarting is spstart -f '*' and the work resumes near where it stopped. Where the printers must stop but the queue must not drain into them afterwards, run ssuspend -y 3600 before starting them again.
Starting at Boot
On a packaged installation the spooler is a system service. The installed unit is:
[Unit]
Description=Xi-Text Print Manager
After=syslog.service
StartLimitIntervalSec=30
StartLimitBurst=5
[Service]
ExecStart=/usr/local/bin/spstart 2000 50
ExecStop=/usr/local/bin/sstop -y
Restart=on-failure
RestartSec=5
Type=forking
TimeoutStopSec=330
KillMode=mixed
[Install]
WantedBy=printer.target
Two details in it matter. TimeoutStopSec=330 is there because a graceful stop halts every printer, syncs the spool and only then releases the shared memory; under load that exceeds the 90-second default, and a shutdown killed part-way leaves shared-memory segments behind. Some installation routes write a shorter unit without that setting, and no route replaces an existing unit file on upgrade - so check the unit on an existing installation before restarting a busy system.
The unit starts the spooler. It leaves the printers halted, so spstart -f '*' belongs in the site's own startup arrangements after it. The commands are installed in /usr/local/bin.
Monitoring During Bulk Operations
Watch the states from a second terminal:
splist -H -F "%p %s %j"
Run it repeatedly with whatever the platform provides. The watch command is convenient where it exists and is absent on the commercial Unix platforms, so a portable loop is:
while true
do
splist -H -F "%p %s %j"
sleep 5
done
To count printers by state:
splist -F "%s" | sort | uniq -c
To list the ones still running:
splist -F "%p %t" | grep -v halted
Privileges
Starting and stopping printers is an ordinary user's action. spstart, sphalt, spstop and spinter require the halt/go privilege, which is in the default privilege set, so most users can run a bulk halt. Approving alignment with spok and spnok requires the printer-queue privilege, also a default. Stopping the spooler with sstop, ssuspend or srelease requires the spooler-stop privilege, which is absent from the default set - root and the system user are accepted as well. Acting on another host's printers requires the remote-printer privilege. splist and spstat require none.
Two consequences are worth planning for: an ordinary user can halt every printer on the host with one command, and the operator who has to run sstop during the window may need a privilege they do not normally hold.
Troubleshooting
A printer will not stop. If sphalt leaves it running, it is waiting for the job in progress to finish, which is a long time on a large job or a slow device. spstop ends it now. A printer stuck in shutdown is waiting for the device to accept the closing strings - commonly XOFF flow control from a printer that is out of paper or switched offline.
A printer will not start. The reason is in the system report file, which lives in the spool directory:
tail -50 /var/spool/xi/spd/spshed_reps
The usual causes are a parse error in the printer's setup file, a device that is neither a character device nor a FIFO, an alignment file that cannot be read, and a mismatch between a network device and its filter. A printer's setup files are in its own directory under the printers directory:
ls -l /var/spool/xi/printers/lp1/
The paths on a given installation may differ. Both directories are settings in the master configuration file /etc/xi/textconfig - SPOOLDIR and SPOOLPT - and the values above are the compiled-in defaults a packaged installation uses.
Printers are idle with jobs queued. Check whether scheduling is suspended (nothing displays it, so run srelease if in doubt), then check the job's form type against the printer's, the job's class code, the job's hold time, and the printer's size limits.
A permission error. See Privileges above; the message names the operation that was refused.
Best Practices
Before stopping all printers:
- Notify users of the maintenance window
- Save the printer states with splist -H - the one step that makes the restart verifiable
- Check for critical jobs in the queue with sqlist
- Prefer sphalt over spstop wherever the time can be spared
After restarting:
- Compare splist against the record saved beforehand, printer by printer
- Read spshed_reps for anything that failed to start silently
- Answer the alignment prompt on every printer that uses one
- Watch the first few jobs through
Quick Reference
| Command | Effect |
|---|---|
| splist -H | List every printer, with a header |
| sphalt -f '*' | Halt every local printer at the end of its current job |
| spstop -f '*' | Stop every local printer now; jobs return to the queue |
| spinter -f '*' | Interrupt every local printer; jobs return to the queue |
| spstart -f '*' | Start every local printer that is halted, offline or in error |
| spstat <printer> | Exit 0 if that printer is running |
| ssuspend -y <seconds> | Stop handing queued jobs to printers |
| srelease | Resume handing out jobs |
| sstop -y | Stop the spooler; halts every printer immediately first |
| spstart 2000 50 | Start the spooler; leaves every printer halted |
The bulk operations exist and are one command each. The care belongs in the two places the product leaves to the administrator: recording what was running before it was stopped, and checking that everything came back afterwards.