Previous Section  < Day Day Up >  Next Section

10.2. Environment Customization

Like the Bourne shell, bash uses the file /etc/profile for system-wide customization. When a user logs in, the shell reads and runs /etc/profile before running the user's .bash_profile.

We won't cover all the possible commands you might want to put in /etc/profile. But bash has a few unique features that are particularly relevant to system-wide customization; we'll discuss them here.

We'll start with two built-in commands that you can use in /etc/profile to tailor your users' environments and constrain their use of system resources. Users can also use these commands in their .bash_profile, or at any other time, to override the default settings.

10.2.1. umask

umask, like the same command in most other shells, lets you specify the default permissions that files have when users create them. It takes the same types of arguments that the chmod command does, i.e., absolute (octal numbers) or symbolic permission values.

The umask contains the permissions that are turned off by default whenever a process creates a file, regardless of what permission the process specifies.[8]

[8] If you are comfortable with Boolean logic, think of the umask as a number that the operating system logically ANDs with the permission given by the creating process.

We'll use octal notation to show how this works. As you probably know, the digits in a permission number stand (left to right) for the permissions of the owner, owner's group, and all other users, respectively. Each digit, in turn, consists of three bits, which specify read, write, and execute permissions from left to right. (If a file is a directory, the "execute" permission becomes "search" permission, i.e., permission to cd to it, list its files, etc.)

For example, the octal number 640 equals the binary number 110 100 000. If a file has this permission, then its owner can read and write it; users in the owner's group can only read it; everyone else has no permission on it. A file with permission 755 gives its owner the right to read, write, and execute it and everyone else the right to read and execute (but not write).

022 is a common umask value. This implies that when a file is created, the "most" permission it could possibly have is 755—which is the usual permission of an executable that a compiler might create. A text editor, on the other hand, might create a file with 666 permission (read and write for everyone), but the umask forces it to be 644 instead.

10.2.2. ulimit

The ulimit command was originally used to specify the limit on file creation size. But bash's version has options that let you put limits on several different system resources. Table 10-2 lists the options.

Table 10-2. ulimit resource options

Option

Resource limited

-a

All limits (for printing values only)

-c

Core file size (1 Kb blocks)

-d

Process data segment (Kb)

-f

File size (1 Kb blocks)

-l

Maximum size of a process that can be locked in memory (Kb)[9]

-m

Maximum resident set size

-n

File descriptors

-p

Pipe size (512 byte blocks)

-s

Process stack segment (Kb)

-t

Process CPU time (seconds)

-u

Maximum number of processes available to a user

-v

Virtual memory (Kb)


[9] Not available in versions of bash prior to 2.0.

Each takes a numerical argument that specifies the limit in units shown in the table. You can also give the argument "unlimited" (which may actually mean some physical limit), "hard" and "soft", which refer to the current hard and soft limits (see below), or you can omit the argument, in which case it will print the current limit. ulimit -a prints limits (or "unlimited") of all types.[10] You can specify only one type of resource at a time. If you don't specify any option, -f is assumed.

[10] The "hard" and "soft" arguments are not available in bash prior to version 2.05a.

Some of these options depend on operating system capabilities that don't exist in older UNIX versions. In particular, some older versions have a fixed limit of 20 file descriptors per process (making -n irrelevant), and some don't support virtual memory (making -v irrelevant).

The -d and -s options have to do with dynamic memory allocation, i.e., memory for which a process asks the operating system at runtime. It's not necessary for casual users to limit these, though software developers may want to do so to prevent buggy programs from trying to allocate endless amounts of memory due to infinite loops.

The -v and -m options are similar; -v puts a limit on all uses of memory, and -m limits the amount of physical memory that a process is allowed to use. You don't need these unless your system has severe memory constraints or you want to limit process size to avoid thrashing.

The -u option is another option which is useful if you have system memory constraints or you wish just wish to stop individual users from hogging the system resources.

You may want to specify limits on file size (-f and -c) if you have constraints on disk space. Sometimes users actually mean to create huge files, but more often than not, a huge file is the result of a buggy program that goes into an infinite loop. Software developers who use debuggers like sdb, dbx, and gdb should not limit core file size, because core dumps are necessary for debugging.

The -t option is another possible guard against infinite loops. However, a program that is in an infinite loop but isn't allocating memory or writing files is not particularly dangerous; it's better to leave this unlimited and just let the user kill the offending program.

In addition to the types of resources you can limit, ulimit lets you specify hard or soft limits. Hard limits can be lowered by any user but only raised by the super user (root); users can lower soft limits and raise them—but only as high as the hard limit for that resource.

If you give -H along with one (or more) of the options above, ulimit will set hard limits; -S sets soft limits. Without either of these, ulimit sets the hard and soft limit. For example, the following commands set the soft limit on file descriptors to 64 and the hard limit to unlimited:

ulimit -Sn 64

ulimit -Hn unlimited

When ulimit prints current limits, it prints soft limits unless you specify -H.

10.2.3. Types of Global Customization

The best possible approach to globally available customization would be a system-wide environment file that is separate from each user's environment file—just like /etc/profile is separate from each user's .bash_profile. Unfortunately, bash doesn't have this feature.

Nevertheless, the shell gives you a few ways to set up customizations that are available to all users at all times. Environment variables are the most obvious; your /etc/profile file will undoubtedly contain definitions for several of them, including PATH and TERM.

The variable TMOUT is useful when your system supports dialup lines. Set it to a number N, and if a user doesn't enter a command within N seconds after the shell last issued a prompt, the shell will terminate. This feature is helpful in preventing people from "hogging" the dialup lines.

You may want to include some more complex customizations involving environment variables, such as the prompt string PS1 containing the current directory (as seen in Chapter 4).

You can also turn on options, such as emacs or vi editing modes, or noclobber to protect against inadvertent file overwriting. Any shell scripts you have written for general use also contribute to customization.

Unfortunately, it's not possible to create a global alias. You can define aliases in /etc/profile, but there is no way to make them part of the environment so that their definitions will propagate to subshells. (In contrast, users can define global aliases by putting their definitions in ~/.bashrc.)

However, you can set up global functions. These are an excellent way to customize your system's environment, because functions are part of the shell, not separate processes.

    Previous Section  < Day Day Up >  Next Section