Documenting how an application works, its purpose, and its intended usage is really important, even if it is just a simple shell script we are talking about. To ease code maintenance in the most basic cases, documentation can be embed directly inside scripts. In this tutorial we learn how to include Pearl’s Plain Old Documentation syntax (POD) in bash scripts, and how to convert it to various formats using pod2 utilities such as pod2man and pod2html.
In this tutorial you will learn:
- How to embed POD-formatted documentation in Bash scripts using Heredoc and do-nothing constructs
- How to convert POD documentation in various formats using pod2 utilities
|Category||Requirements, Conventions or Software Version Used|
|Software||Bash, pod2 utilities|
|Other||Privileged access to your Linux system as root or via the
|Conventions||# – requires given linux-commands to be executed with root privileges either directly as a root user or by use of
$ – requires given linux-commands to be executed as a regular non-privileged user
The Heredoc and do-nothing constructs
To embed documentation inside Bash scripts we can make use of two constructs: “Heredoc” and “do-nothing”. The former makes it possible to pass a multi-line input to a specific command. It can be used, for example, to print a multi-line message to standard output, without repeating an
echo command multiple times. Instead of writing:
echo "Script usage:" echo " myscript [options] argument" echo "" echo "Options:" echo " -h, --help Show this message" echo " -f, --foo This option does foo" echo " -b, --bar This option does bar"
We would write:
cat << EOF Script usage: myscript [options] argument Options: -h, --help Show this message -f, --foo This option does foo -b, --bar This option does bar EOF
The second snippet, as you can see, is much cleaner (and faster to type). The syntax of an “Heredoc” construct is quite simple: at the left of the
<< operator we write the command we want to pass the multi-line input to; at the right of the operator, instead, we pass a delimiter, (EOF is often used, but it is just a standard), which marks the end of the Heredoc. If the delimiter is unquoted, variables inside the document are expanded.
We can use the “Heredoc” construct to embed documentation inside a Bash script. In such situation, however, we don’t want to execute any command: here is where the “do-nothing” construct comes in to play.
: is a
Null command: it does nothing and always exits successfully (its exist status is always
0). Using the two constructs together, we can embed documentation in shell scripts, the following way:
#!/bin/bash # # Bash code goes here # exit 0 : << EOF Script usage: myscript [options] argument Options: -h, --help Show this message -f, --foo This option does foo -b, --bar This option does bar EOF
Notice I explicitly added an
exit 0 instruction just before the documentation section: this is to avoid the shell processing that part when the script is executed.
Using the Perl’s Plain Old Documentation format
In the examples above, the script documentation consisted just of plain text. To produce well formatted documents, however, we can use the Perl’s Plain Old Documentation (POD) format. Here is an example which uses a minimal set of commands:
: << EOF =pod =head1 NAME Here is a brief description of what are script does. =head1 SYNOPSYS scriptname [options] argument =head1 OPTIONS -h, --help Show this message -f, --foo This option does foo -b, --bar This option does bar =cut EOF
The first “command paragraph” we used in the example is
=pod. It just signals the start of the POD document. In this case it is superfluous, since any command starts the document block; it can be useful, however, when the documentation should start with ordinary text. We then used
=head1, which produces a level 1 heading (levels go from 1 to 6). Finally, we used
=cut, which signals the end a POD block. A blank line must precede the command, and another one must follow it.
Extracting and generating documentation with pod2 programs
Once we finished describing the functionalities of our script, we can use “pod2” utilities to generate various type of documents such as a roff or HTML pages, which are readable, with the “man” utility and with any web browser, respectively.
On Archlinux and Debian, pod2 utilities are part of the “perl” package, which should be already installed on your system. To explicitly install the package on the former distribution, however, we can run:
$ sudo pacman -S perl
On the latter, instead, we use
$ sudo apt install perl
On Fedora and other distributions based on it, pod2 utilities ships into separate packages. The “perl-podlators” package includes pod2man, while “perl-Pod-Html” provides pod2html. We can install them using
$ sudo dnf install perl-podlators perl-Pod-Html
To generate a roff page, we invoke pod2man and pass the script path as argument, than we redirect the utility stdout to a file:
$ pod2man testscript.sh > testscript.1
We can read the document by running:
$ man ./testscript.1
To make the page available system-wide, so that we can read it without providing its full path, we can copy it into the
To generate the HTML version of the document, instead, we use pod2html:
$ pod2html testscript.sh > testscript.html
In this tutorial we learned how to embed documentation inside Bash scripts using “Heredoc” and “do-nothing” constructs. We saw how to use Perl’s Plain Old Documentation syntax, and how to generate roff and HTML-formatted pages based on it, using the pod2man and pod2html utilities.