Skip to content
VLSI Mentor

Perl Part I · Module 1 · Introduction to Perl

STDIN, STDOUT and STDERR

Every program you run has three channels open to it: one it can read from, one for its normal output, and one for messages about problems. On your terminal all three look identical, which is exactly why beginners never notice them — and why so many scripts become unusable the moment another program tries to read their output. This chapter separates the three, shows what redirecting each one does, and establishes the habit that makes a script into a tool: results on one stream, complaints on the other, always.

Foundation14 min readPerlPart IFundamentalsStreamsSTDERR

Part I · Module 1 · Chapter 1.7 · STDIN, STDOUT and STDERR

1. The Problem With One Channel

Chapter 1.6 ended with a warning: in Part II, the thing reading your output is usually another program. Here is the problem that creates.

Imagine a script whose job is to print one word — PASS or FAIL — so that a calling script can act on it. Now it also needs to mention that the log it read looked truncated. If both go to the same place, the caller receives:

Azvya Education Pvt. Ltd.VLSI Mentor
What the caller sees when everything shares one channel
note: log was truncated
PASS

The caller wanted one word and got two lines. It now has to guess which line is the answer. Every heuristic it could use — take the last line, skip lines starting with note — is a guess that will be wrong eventually.

The fix is not cleverer parsing. It is to use the second channel that was there all along.

2. The Three Standard Streams

Every program starts with three streams already open:

  • STDIN — standard input. Where the program reads from, if it reads anything.
  • STDOUT — standard output. Where its results go. This is where print sends things by default.
  • STDERR — standard error. Where messages about the run go: warnings, progress notes, failures.

The distinction is about the kind of information, not its severity. STDOUT carries what the program was asked to produce. STDERR carries everything else — including notes that are not errors at all.

A left-to-right flow. STDIN, standard input, feeds into the script in the centre. Two separate arrows leave the script: one upward to STDOUT, standard output, carrying results; one downward to STDERR, standard error, carrying warnings and progress notes.STDINinput, if anyyour scriptcheck.plSTDOUTthe resultSTDERRnotes and problems12
Figure 1 — the three streams. Input arrives on one channel; two separate channels leave. The split on the right is the whole point of the chapter: because they are separate, whoever runs your script can send the result to a file and still see the notes, or discard the notes and keep only the result.

3. Choosing a Stream

Name the stream between print and what you want written. There is no comma after it:

Azvya Education Pvt. Ltd.VLSI Mentor
streams.pl
use strict;
use warnings;

print STDOUT "result: PASS\n";
print STDERR "note: log was truncated\n";

Run it on a terminal and both lines appear, which is precisely why the distinction is invisible until you look for it:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — both streams, terminal
note: log was truncated
result: PASS

A plain print "..." with no stream named goes to STDOUT. Every print you have written so far has been writing to STDOUT without saying so.

4. Separating Them

The separation becomes real when you send the streams to different places. Your shell does that with redirections:

Azvya Education Pvt. Ltd.VLSI Mentor
Keep only the result; throw the notes away
perl streams.pl 2>/dev/null
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
result: PASS
Azvya Education Pvt. Ltd.VLSI Mentor
Keep only the notes
perl streams.pl 2>&1 1>/dev/null
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
note: log was truncated
Azvya Education Pvt. Ltd.VLSI Mentor
Result into a file; notes still on your screen
perl streams.pl > out.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Captured — what landed in out.txt
result: PASS

The 2 in 2> is STDERR's number; STDOUT is 1. That is all the shell syntax this chapter needs. What matters is the consequence: whoever runs your script gets to decide where each kind of information goes — but only if you put it on the right stream in the first place.

5. Reading From STDIN

To read, use <STDIN>, which gives you one line. It has to be stored somewhere, which needs a variable:

Azvya Education Pvt. Ltd.VLSI Mentor
read-line.pl
use strict;
use warnings;

my $line = <STDIN>;
print "you typed: $line";

my $line declares a variable — a name holding one value. Writing it inside double quotes, as "you typed: $line", replaces it with its value; that substitution is called interpolation and Chapter 4.2 covers it in full. Module 2 covers variables properly, and Chapter 1.10 explains why the my is compulsory.

Give it input by typing, or by piping from another command:

Azvya Education Pvt. Ltd.VLSI Mentor
Feeding it from another command
printf 'alu_smoke\n' | perl read-line.pl
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
you typed: alu_smoke

Notice there is no \n in that print, and the output is still on its own line. The newline came in with the input and is still attached to it — a detail that causes real confusion later, and which Chapter 4.9 fixes with chomp.

What if there is no input at all? The variable gets no value, and with warnings on Perl says so:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — empty input
Use of uninitialized value $line in concatenation (.) or string at read-line.pl line 5.
you typed:

That message is a preview of Chapter 1.11. For now, read it as what it says: the program expected a line and did not get one.

6. The Order You See Is Not Guaranteed

Something measured and worth knowing before it confuses you. In §3 the output appeared as:

Azvya Education Pvt. Ltd.VLSI Mentor
Captured output — note the order
note: log was truncated
result: PASS

The STDERR line came out first, even though its print is second in the file. Nothing is wrong, and Perl did not reorder your statements.

The reason is buffering. When STDOUT is not a terminal — when it is redirected into a file or a pipe — Perl collects output and writes it in blocks, for speed. STDERR is not buffered that way, because a message about a problem is useless if it arrives after the program has crashed. So the unbuffered stream can overtake the buffered one.

The practical rule: do not rely on the relative order of STDOUT and STDERR lines. Within one stream, order is exactly as written. Across the two, it is not. This is the real explanation for the interleaving you may have noticed in Chapter 1.5, where an error appeared above the output that preceded it.

7. Mistakes and How They Look

Diagnostics on STDOUT. The script works perfectly by hand and corrupts a downstream file. Symptom: a consumer reports a strange value, and the "value" turns out to be your progress message. This is the most consequential mistake in the chapter.

A comma after the stream name. print STDERR, "..." is wrong — there is no comma. With warnings on, Perl will complain about it; Chapter 1.1 §7 met this family of message, where the real cause is punctuation and the text talks about filehandles.

Expecting 2>/dev/null to silence a failure. It silences the message, not the problem. The script still failed; you have only stopped hearing about it. Exit status, in Module 15, is how a caller detects the failure regardless of where the text went.

Assuming STDIN always has something. If nothing is piped in and nothing is typed, <STDIN> yields no value, as §5 showed.

8. Why This Matters in Engineering Work

This is the chapter where your scripts begin behaving like tools rather than exercises, and it is worth being concrete about why.

An overnight regression runs hundreds of steps, and each step's output is consumed by the next. A script that prints PASS on STDOUT and everything else on STDERR can be used two ways at once: the automation captures STDOUT and gets a clean answer, while a human watching the terminal sees the progress notes. A script that mixes them can be used only one way — carefully, by someone who knows its quirks.

The same separation is what makes a log file useful after the fact. Results in one file, diagnostics in another, is the difference between "the run produced 400 lines" and "the run produced 400 results and 12 warnings, here they are."

None of this requires knowing about EDA tools. It requires one decision per print: is this the answer, or is this about the answer?

9. What You Should Be Able to Say Now

  1. Every program has three streams: STDIN to read from, STDOUT for results, STDERR for messages about the run.
  2. A plain print writes to STDOUT; name a stream with print STDERR "..." and no comma.
  3. The shell can send each stream somewhere different — 2>/dev/null, > file — but only if you used the right one.
  4. STDERR is for anything that is not the result, including notes that are not errors.
  5. <STDIN> reads one line, keeps its trailing newline, and yields no value when input has run out.
  6. Relative ordering between STDOUT and STDERR is not guaranteed, because one is buffered and the other is not.

10. Exercise

Exercise 1 — separate them. Write verdict.pl that prints PASS to STDOUT and checked 1 log to STDERR. Run it three ways: plain, with 2>/dev/null, and with > result.txt. Record what you see each time and what result.txt contains.

Exercise 2 — predict the consumer's view. A calling script will read only your STDOUT. Explain in one sentence what it receives in each of the three runs above, and why run two and run three give it the same thing.

Exercise 3 — read input. Write a script that reads one line from STDIN and prints it back with the prefix got: . Run it by piping a word in, then run it again with no input at all and record the warning.

Exercise 4 — reason about order. Your script prints three STDOUT lines and one STDERR line, and a colleague reports the STDERR line appearing in the middle of a redirected log. Explain why that is expected, and what you would change if the order genuinely mattered.

11. Summary

  • Three streams, two of them outgoing. STDOUT carries what was asked for; STDERR carries everything about the run.
  • The test is "is this the answer?" — not "is this serious?". Progress notes belong on STDERR even though nothing is wrong.
  • Redirection makes the separation useful, letting one run serve an automated consumer and a watching human at once.
  • <STDIN> reads one line including its newline, and yields nothing when input is exhausted.
  • Cross-stream order is not guaranteed because STDOUT buffers when it is not a terminal and STDERR does not.
  • Mixing them is the mistake that survives testing, because a terminal hides it and a program does not.

You can now choose where your output goes. Chapter 1.8 steps back to the shape of the code itself — what counts as one statement, and what the braces around a group of them actually do.

Where this fits

Part of the Perl curriculum.