mktemp command, trap command

Bash scripts sometimes need to create temporary files or temporary directories. A common practice is to create files or directories in the /tmp directory. There are many drawbacks to doing so. Using the mktemp command is the safest way.

Security issues of temporary files

Creating temporary files directly, especially in the /tmp directory, often leads to security problems.

First of all, the /tmp directory is readable and writable by everyone, and any user can write files in this directory. The temporary files created are also readable by everyone.

$ touch /tmp/info.txt
$ ls -l /tmp/info.txt
-rw-r--r-- 1 ruanyf ruanyf 0 December 28 17:12 /tmp/info.txt

The above command creates a file directly in the /tmp directory, which is readable by everyone by default.

Second, if the attacker knows the file name of the temporary file, he can create a symbolic link to link to the temporary file, which may cause the system to operate abnormally. The attacker may also provide some malicious data to the script. Therefore, it is best to use unpredictable and different file names for temporary files to prevent them from being used.

Finally, the temporary files are used up and should be deleted. However, when the script exits unexpectedly, it often neglects to clean up temporary files.

Generate temporary files should follow the following rules.

-Check if the file already exists before creating. -Ensure that the temporary file has been successfully created. -Temporary files must have permission restrictions. -Use unpredictable file names for temporary files. -When the script exits, delete the temporary files (using the trap command).

Usage of mktemp command

The mktemp command is designed for safe creation of temporary files. Although it does not check whether the temporary file exists before creating a temporary file, it supports a unique file name and a cleanup mechanism, so it can reduce the risk of security attacks.

Run the mktemp command directly to generate a temporary file.

$ mktemp
/tmp/tmp.4GcsWSG4vj

$ ls -l /tmp/tmp.4GcsWSG4vj
-rw------- 1 ruanyf ruanyf 0 December 28 12:49 /tmp/tmp.4GcsWSG4vj

In the above command, the temporary file name generated by the mktemp command is random, and the permission is only the user can read and write.

The usage of Bash script using mktemp command is as follows.

#!/bin/bash

TMPFILE=$(mktemp)
echo "Our temp file is $TMPFILE"

In order to ensure that the temporary file is successfully created, it is best to use the OR operator (||) after the mktemp command to ensure that the script exits when the creation fails.

#!/bin/bash

TMPFILE=$(mktemp) || exit 1
echo "Our temp file is $TMPFILE"

To ensure that the temporary files are deleted when the script exits, you can use the trap command to specify the cleanup operation when exiting.

#!/bin/bash

trap'rm -f "$TMPFILE"' EXIT

TMPFILE=$(mktemp) || exit 1
echo "Our temp file is $TMPFILE"

Parameters of the mktemp command

The -d parameter can create a temporary directory.

$ mktemp -d
/tmp/tmp.Wcau5UjmN6

The -p parameter can specify the directory where the temporary file is located. The default is to use the directory specified by the $TMPDIR environment variable. If this variable is not set, the /tmp directory is used.

$ mktemp -p /home/ruanyf/
/home/ruanyf/tmp.FOKEtvs2H3

The -t parameter can specify the file name template of the temporary file. The end of the template must contain at least three consecutive X characters, indicating random characters. It is recommended to use at least six X. The default file name template is tmp. followed by ten random characters.

$ mktemp -t mytemp.XXXXXXX
/tmp/mytemp.yZ1HgZV

trap command

The trap command is used to respond to system signals in Bash scripts.

The most common system signal is SIGINT (interrupt), which is the signal generated by pressing Ctrl + C. The -l parameter of the trap command can list all system signals.

$ trap -l
 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

The command format of trap is as follows.

$ trap [action] [signal 1] [signal 2] ...

In the above code, "action" is a Bash command, and "signals" are commonly used as follows.

-HUP: No. 1, the script is disconnected from the terminal where it is located. -INT: No. 2, the user presses Ctrl + C, intent to terminate the script. -QUIT: No. 3, the user presses Ctrl + slash, intent to exit the script. -KILL: No. 9, this signal is used to kill the process. -TERM: No. 15, which is the default signal issued by the kill command. -EXIT: No. 0, this is not a system signal, but a signal unique to the Bash script. No matter what the situation, it will be generated as long as the script is exited.

The trap command in response to the EXIT signal is written as follows.

$ trap'rm -f "$TMPFILE"' EXIT

In the above command, when the script encounters the EXIT signal, it will execute rm -f "$TMPFILE".

A common usage scenario of the trap command is to specify the cleanup command to be executed upon exit in the Bash script.

#!/bin/bash

trap'rm -f "$TMPFILE"' EXIT

TMPFILE=$(mktemp) || exit 1
ls /etc> $TMPFILE
if grep -qi "kernel" $TMPFILE; then
  echo'find'
fi

In the above code, whether it is the normal execution of the script ends or the user presses Ctrl + C to terminate, the EXIT signal will be generated, which triggers the deletion of the temporary file.

Note that the trap command must be placed at the beginning of the script. Otherwise, any command above it that causes the script to exit will not be caught by it.

If trap needs to trigger multiple commands, you can encapsulate a Bash function.

function egress {
  command1
  command2
  command3
}

trap egress EXIT