Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting
Prev |  | Next

# Chapter 29. `/dev` and `/proc`

A Linux or UNIX filesystem typically has the `/dev` and `/proc` special-purpose directories.

# 29.1. `/dev`

The `/dev` directory contains entries for the physical devices that may or may not be present in the hardware. [1] Appropriately enough, these are called device files. As an example, the hard drive partitions containing the mounted filesystem(s) have entries in `/dev`, as df shows.

     bash$ df
     Filesystem           1k-blocks      Used Available Use%
     Mounted on
     /dev/hda6               495876    222748    247527  48% /
     /dev/hda1                50755      3887     44248   9% /boot
     /dev/hda8               367013     13262    334803   4% /home
     /dev/hda5              1714416   1123624    503704  70% /usr

Among other things, the `/dev` directory contains loopback devices, such as `/dev/loop0`. A loopback device is a gimmick that allows an ordinary file to be accessed as if it were a block device. [2] This permits mounting an entire filesystem within a single large file. See Example 17-8 and Example 17-7.

A few of the pseudo-devices in `/dev` have other specialized uses, such as `/dev/null`, `/dev/zero`, `/dev/urandom`, `/dev/sda1` (hard drive partition), `/dev/udp` (User Datagram Packet port), and `/dev/tcp`.

For instance:

To manually mount a USB flash drive, append the following line to `/etc/fstab`. [3]

       1 /dev/sda1    /mnt/flashdrive    auto    noauto,user,noatime    0 0

(See also Example A-23.)

Checking whether a disk is in the CD-burner (soft-linked to `/dev/hdc`):

       1 head -1 /dev/hdc
       2
       3
       4 #  head: cannot open '/dev/hdc' for reading: No medium found
       5 #  (No disc in the drive.)
       6
       7 #  head: error reading '/dev/hdc': Input/output error
       8 #  (There is a disk in the drive, but it can't be read;
       9 #+  possibly it's an unrecorded CDR blank.)
      10
      11 #  Stream of characters and assorted gibberish
      12 #  (There is a pre-recorded disk in the drive,
      13 #+ and this is raw output -- a stream of ASCII and binary data.)
      14 #  Here we see the wisdom of using 'head' to limit the output
      15 #+ to manageable proportions, rather than 'cat' or something similar.
      16
      17
      18 #  Now, it's just a matter of checking/parsing the output and taking
      19 #+ appropriate action.

When executing a command on a `/dev/tcp/$host/$port` pseudo-device file, Bash opens a TCP connection to the associated socket.

The following examples assume an active Internet connection.

Getting the time from `nist.gov`:

     bash$ cat </dev/tcp/time.nist.gov/13
     53082 04-03-18 04:26:54 68 0 0 502.3 UTC(NIST) *

[Mark contributed this example.]

Generalizing the above into a script:

       1 #!/bin/bash
       2 # This script must run with root permissions.
       3
       4 URL="time.nist.gov/13"
       5
       6 Time=$(cat </dev/tcp/"$URL")
       7 UTC=$(echo "$Time" | awk '{print$3}')   # Third field is UTC (GMT) time.
       8 # Exercise: modify this for different time zones.
       9
      10 echo "UTC Time = "$UTC""

Downloading a URL:

     bash$ exec 5<>/dev/tcp/www.net.cn/80
     bash$ echo -e "GET / HTTP/1.0\n" >&5
     bash$ cat <&5

[Thanks, Mark and Mihai Maties.]

Example 29-1. Using `/dev/tcp` for troubleshooting

       1 #!/bin/bash
       2 # dev-tcp.sh: /dev/tcp redirection to check Internet connection.
       3
       4 # Script by Troy Engel.
       5 # Used with permission.
       6
       7 TCP_HOST=news-15.net       # A known spam-friendly ISP.
       8 TCP_PORT=80                # Port 80 is http.
       9
      10 # Try to connect. (Somewhat similar to a 'ping' . . .)
      11 echo "HEAD / HTTP/1.0" >/dev/tcp/${TCP_HOST}/${TCP_PORT}
      12 MYEXIT=$?
      13
      14 : <<EXPLANATION
      15 If bash was compiled with --enable-net-redirections, it has the capability of
      16 using a special character device for both TCP and UDP redirections. These
      17 redirections are used identically as STDIN/STDOUT/STDERR. The device entries
      18 are 30,36 for /dev/tcp:
      19
      20   mknod /dev/tcp c 30 36
      21
      22 >From the bash reference:
      23 /dev/tcp/host/port
      24     If host is a valid hostname or Internet address, and port is an integer
      25 port number or service name, Bash attempts to open a TCP connection to the
      26 corresponding socket.
      27 EXPLANATION
      28
      29
      30 if [ "X$MYEXIT" = "X0" ]; then
      31   echo "Connection successful. Exit code: $MYEXIT"
      32 else
      33   echo "Connection unsuccessful. Exit code: $MYEXIT"
      34 fi
      35
      36 exit $MYEXIT

Example 29-2. Playing music

       1 #!/bin/bash
       2 # music.sh
       3
       4 # Music without external files
       5
       6 # Author: Antonio Macchi
       7 # Used in ABS Guide with permission.
       8
       9
      10 #  /dev/dsp default = 8000 frames per second, 8 bits per frame (1 byte),
      11 #+ 1 channel (mono)
      12
      13 duration=2000       # If 8000 bytes = 1 second, then 2000 = 1/4 second.
      14 volume=$'\xc0'      # Max volume = \xff (or \x00).
      15 mute=$'\x80'        # No volume = \x80 (the middle).
      16
      17 function mknote ()  # $1=Note Hz in bytes (e.g. A = 440Hz ::
      18 {                   #+ 8000 fps / 440 = 16 :: A = 16 bytes per second)
      19   for t in `seq 0 $duration`
      20   do
      21     test $(( $t % $1 )) = 0 && echo -n $volume || echo -n $mute
      22   done
      23 }
      24
      25 e=`mknote 49`
      26 g=`mknote 41`
      27 a=`mknote 36`
      28 b=`mknote 32`
      29 c=`mknote 30`
      30 cis=`mknote 29`
      31 d=`mknote 27`
      32 e2=`mknote 24`
      33 n=`mknote 32767`
      34 # European notation.
      35
      36 echo -n "$g$e2$d$c$d$c$a$g$n$g$e$n$g$e2$d$c$c$b$c$cis$n$cis$d \
      37 $n$g$e2$d$c$d$c$a$g$n$g$e$n$g$a$d$c$b$a$b$c" > /dev/dsp
      38 # dsp = Digital Signal Processor
      39
      40 exit      # A "bonny" example of an elegant shell script!

### Notes

[1] | The entries in `/dev` provide mount points for physical and virtual devices. These entries use very little drive space. Some devices, such as `/dev/null`, `/dev/zero`, and `/dev/urandom` are virtual. They are not actual physical devices and exist only in software.
[2] | A block device reads and/or writes data in chunks, or blocks, in contrast to a character device, which acesses data in character units. Examples of block devices are hard drives, CDROM drives, and flash drives. Examples of character devices are keyboards, modems, sound cards.
[3] | Of course, the mount point `/mnt/flashdrive` must exist. If not, then, as root, mkdir /mnt/flashdrive. To actually mount the drive, use the following command: mount /mnt/flashdrive Newer Linux distros automount flash drives in the `/media` directory without user intervention.

Prev | Home | Next
Indirect References | Up | `/proc`