Avoid /tmp use on Unix

Inline Edit | Shared Known File Location

On Unix, never write shell code such as:

# dump user crontab, edit, then reload it
crontab -l > /tmp/cron.$$
# munge cron.$$ file here
crontab < /tmp/cron.$$

The cron.$$ file poses a security risk. For more information, see Perl and Temporary Files. This page outlines various alternatives. If only a single program will use the data, edit the data in memory. Use pipe chains to pass the data between different programs. For lock files, use a static location outside the /tmp directory. If different programs must access the temporary file by name, run mktemp(1) to generate a shareable filename.

Inline Edit

If only one program needs to edit the data, either edit the data in a pipe chain, or store the data in a variable. For example, entries in the crontab(5) file could be removed without a temporary file:

crontab -l | grep -v rdate | crontab -

This pipe chain lists the existing crontab(5) entries, removes any containing the string rdate, then reloads the resulting data by piping it back to crontab(1). No useless temporary file, no security risk. New crontab(5) entries can be added using a subshell:

crontab -l

cat <<'EOF'
@daily $HOME/bin/check-expire -f $HOME/share/check-expire.cfg \
openssl_x509 -in /etc/ssl/mail.crt

) | crontab -

Another option: use a variable to store the data. This allows line-by-line inspection of the data difficult to do in a pipe chain.

CRON_DATA=`crontab -l`

# alter CRON_DATA contents here

echo $CRON_DATA | crontab -

Sidenote: when editing data, also consider the ramifications of running the code again. The above grep -v rdate will always remove lines containing the string rdate. However, the @daily addition will be duplicated every time the code is run. Test whether the line exists before adding it! CFEngine supports this via an AppendIfNoSuchLine statement used in editfiles blocks. Another option: the Commands::Guarded Perl module.

Shared Known File Location

If applications require a shared known file location, for example a lockfile, do not use /tmp. Instead, store the file under a new directory that the various applications can use, for example a new directory under /var/run. Larger sites running many different flavors of Unix should designate a new site-wide lock directory outside of the various standards used by Unix vendors.