[minidive bash] Basic Features2

pinelancer·2021년 10월 24일
0

minishell

목록 보기
3/6

minishell 기능 구현에 앞서 bash manual 중요한 부분 밑줄 그어가며 읽기3

3.6 Redirection

Before a command is executed, its input and output may be redirected using a special no- tation interpreted by the shell. Redirection allows commands’ file handles to be duplicated, opened, closed, made to refer to different files, and can change the files the command reads from and writes to. Redirection may also be used to modify file handles in the current shell execution environment. The following redirection operators may precede or appear anywhere within a simple command or may follow a command. Redirections are processed in the order they appear, from left to right.

...

In the following descriptions, if the file descriptor number is omitted, and the first character of the redirection operator is ‘<’, the redirection refers to the standard input (file descriptor 0). If the first character of the redirection operator is ‘>’, the redirection refers to the standard output (file descriptor 1).

The word following the redirection operator in the following descriptions, unless other-wise noted, is subjected to brace expansion, tilde expansion, parameter expansion, command substitution, arithmetic expansion, quote removal, filename expansion, and word splitting. If it expands to more than one word, Bash reports an error.

Note that the order of redirections is significant. For example, the command

ls > dirlist 2>&1
directs both standard output (file descriptor 1) and standard error (file descriptor 2) to the

file dirlist, while the command ls 2>&1 > dirlist

directs only the standard output to file dirlist, because the standard error was made a copy of the standard output before the standard output was redirected to dirlist.

Bash handles several filenames specially when they are used in redirections, as described in the following table. ...

...

Redirections using file descriptors greater than 9 should be used with care, as they may conflict with file descriptors the shell uses internally.

3.6.1 Redirecting Input

Redirection of input causes the file whose name results from the expansion of word to be opened for reading on file descriptor n, or the standard input (file descriptor 0) if n is not specified.

The general format for redirecting input is:

[n]<word

3.6.2 Redirecting Output

Redirection of output causes the file whose name results from the expansion of word to be opened for writing on file descriptor n, or the standard output (file descriptor 1) if n is not specified. If the file does not exist it is created; if it does exist it is truncated to zero size.

The general format for redirecting output is:

[n]>[|]word

...

3.6.3 Appending Redirected Output

Redirection of output in this fashion causes the file whose name results from the expansion of word to be opened for appending on file descriptor n, or the standard output (file descriptor 1) if n is not specified. If the file does not exist it is created.

The general format for appending output is:

[n]>>word

3.6.6 Here Documents

This type of redirection instructs the shell to read input from the current source until a line containing only word (with no trailing blanks) is seen. All of the lines read up to that point are then used as the standard input (or file descriptor n if n is specified) for a command.

The format of here-documents is:

[n]<<[]word
	here-document
delimiter

No parameter and variable expansion, command substitution, arithmetic expansion, or filename expansion is performed on word. If any part of word is quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence \newline is ignored, and ‘\’ must be used to quote the characters ‘\’, ‘$’, and ‘‘’

...

After a command has been split into words, if it results in a simple command and an optional list of arguments, the following actions are taken.

3.7 Executing Commands

3.7.1 Simple Command Expansion

When a simple command is executed, the shell performs the following expansions, assign- ments, and redirections, from left to right, in the following order.

  1. The words that the parser has marked as variable assignments (those preceding the command name) and redirections are saved for later processing.
  2. The words that are not variable assignments or redirections are expanded (see Section 3.5 [Shell Expansions], page 22). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments.
Not in manual
%> export rrr=\<
%> ${rrr} 
zsh: command not found: <
  1. Redirections are performed as described above(seeSection3.6[Redirections],page35).
  2. The text after the ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable.

If no command name results, the variable assignments affect the current shell environment. Otherwise, the variables are added to the environment of the executed command and do not affect the current shell environment. If any of the assignments attempts to assign a value to a readonly variable, an error occurs, and the command exits with a non-zero status.

If no command name results, redirections are performed, but do not affect the current shell environment. A redirection error causes the command to exit with a non-zero status.

If there is a command name left after expansion, execution proceeds as described below. Otherwise, the command exits. If one of the expansions contained a command substitu- tion, the exit status of the command is the exit status of the last command substitution performed. If there were no command substitutions, the command exits with a status of zero.

3.7.2 Command Search and Execution

After a command has been split into words, if it results in a simple command and an optional list of arguments, the following actions are taken.

  1. If the command name contains no slashes, the shell attempts to locate it.If there exists a shell function by that name, that function is invoked as described in Section 3.3 [Shell Functions], page 18.
  2. If the name does not match a function, the shell searches for it in the list of shell builtins. If a match is found, that builtin is invoked.
  3. If the name is neither a shell function nor a builtin, and contains no slashes, Bash searches each element of $PATH for a directory containing an executable file by that name. Bash uses a hash table to remember the full pathnames of executable files to avoid multiple PATH searches (see the description of hash in Section 4.1 [Bourne Shell Builtins], page 44). A full search of the directories in $PATH is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell searches for a defined shell function named command_not_found_handle. If that function exists, it is invoked in a separate execution environment with the original command and the original command’s arguments as its arguments, and the function’s exit status becomes the exit status of that subshell. If that function is not defined, the shell prints an error message and returns an exit status of 127.
  4. If the search is successful, or if the command name contains one or more slashes, the shell executes the named program in a separate execution environment. Argument 0 is set to the name given, and the remaining arguments to the command are set to the arguments supplied, if any.
  5. If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell script and the shell executes it as described in Section 3.8 [Shell Scripts], page 42.
  6. If the command was not begun asynchronously, the shell waits for the command to complete and collects its exit status.

3.7.3 Command Execution Environment

The shell has an execution environment, which consists of the following:

  • open files inherited by the shell at invocation, as modified by redirections supplied to the exec builtin

  • the current working directory as set by cd, pushd, or popd, or inherited by the shell at invocation

  • the file creation mode mask as set by umask or inherited from the shell’s parent

  • current traps set by trap

  • shell parameters that are set by variable assignment or with set or inherited from the shell’s parent in the environment

  • shell functions defined during execution or inherited from the shell’s parent in the environment

  • options enabled at invocation (either by default or with command-line arguments) or by set

  • options enabled by shopt (see Section 4.3.2 [The Shopt Builtin], page 66)

  • shell aliases defined with alias (see Section 6.6 [Aliases], page 95)

  • various process ids, including those of background jobs (see Section 3.2.4 [Lists], page 9), the value of $$, and the value of $PPID

    When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment that consists of the following. Unless otherwise noted, the values are inherited from the shell.

    • the shell’s open files, plus any modifications and additions specified by redirections to the command
    • the current working directory
    • the file creation mode mask
    • shell variables and functions marked for export, along with variables exported for the command, passed in the environment (see Section 3.7.4 [Environment], page 41)
    • traps caught by the shell are reset to the values inherited from the shell’s parent, and traps ignored by the shell are ignored

A command invoked in this separate environment cannot affect the shell’s execution environment.

Command substitution, commands grouped with parentheses, and asynchronous com- mands are invoked in a subshell environment that is a duplicate of the shell environment, except that traps caught by the shell are reset to the values that the shell inherited from its parent at invocation. Builtin commands that are invoked as part of a pipeline are also executed in a subshell environment. Changes made to the subshell environment cannot affect the shell’s execution environment.

Subshells spawned to execute command substitutions inherit the value of the -e option from the parent shell. When not in posix mode, Bash clears the -e option in such subshells.

If a command is followed by a ‘&’ and job control is not active, the default standard input for the command is the empty file /dev/null. Otherwise, the invoked command inherits the file descriptors of the calling shell as modified by redirections.

3.7.4 Environment

When a program is invoked it is given an array of strings called the environment. This is a list of name-value pairs, of the form name=value.

Bash provides several ways to manipulate the environment. On invocation, the shell scans its own environment and creates a parameter for each name found, automatically marking it for export to child processes. Executed commands inherit the environment. The export and ‘declare -x’ commands allow parameters and functions to be added to and deleted from the environment. If the value of a parameter in the environment is modified, the new value becomes part of the environment, replacing the old. The environment inherited by any executed command consists of the shell’s initial environment, whose values may be modified in the shell, less any pairs removed by the unset and ‘export -n’ commands, plus any additions via the export and ‘declare -x’ commands.

The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments, as described in Section 3.4 [Shell Parameters], page 20. These assignment statements affect only the environment seen by that command.

If the -k option is set (see Section 4.3.1 [The Set Builtin], page 62), then all parameter assignments are placed in the environment for a command, not just those that precede the command name.

When Bash invokes an external command, the variable ‘$_’ is set to the full pathname of the command and passed to that command in its environment.

3.7.5 Exit Status

The exit status of an executed command is the value returned by the waitpid system call or equivalent function. Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially. Exit statuses from shell builtins and compound commands are also limited to this range. Under certain circumstances, the shell will use special values to indicate specific failure modes.

For the shell’s purposes, a command which exits with a zero exit status has succeeded. A non-zero exit status indicates failure. This seemingly counter-intuitive scheme is used so there is one well-defined way to indicate success and a variety of ways to indicate various failure modes. When a command terminates on a fatal signal whose number is N, Bash uses the value 128+N as the exit status.

If a command is not found, the child process created to execute it returns a status of 127. If a command is found but is not executable, the return status is 126.

If a command fails because of an error during expansion or redirection, the exit status is greater than zero.

The exit status is used by the Bash conditional commands (see Section 3.2.5.2 [Con- ditional Constructs], page 11) and some of the list constructs (see Section 3.2.4 [Lists], page 9).

All of the Bash builtins return an exit status of zero if they succeed and a non-zero status on failure, so they may be used by the conditional and list constructs. All builtins return an exit status of 2 to indicate incorrect usage, generally invalid options or missing arguments.

3.7.6 Signals

When Bash is interactive, in the absence of any traps, it ignores SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin is interruptible). When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT. If job control is in effect (see Chapter 7 [Job Control], page 108), Bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.

Non-builtin commands started by Bash have signal handlers set to the values inherited by the shell from its parent. When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers. Commands run as a result of command substitution ignore the keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Section 7.2 [Job Control Builtins], page 109) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt (see Section 4.3.2 [The Shopt Builtin], page 66), Bash sends a SIGHUP to all jobs when an interactive login shell exits.

If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.

6.3.1 What is an Interactive Shell?

To determine within a startup script whether or not Bash is running interactively, test the value of the ‘-’ special parameter. It contains i when the shell is interactive.

bash-3.2$ case "$-" in
> *i*) echo This shell is interactive ;; 
> *) echo This shell is not interactive ;;
esac
This shell is interactive
bash-3.2$ 

6.3.3 Interactive Shell Behavior

When the shell is running interactively, it changes its behavior in several ways.

  1. Startup files are read and executed as described in Section 6.2 [Bash Startup Files], page 89.

  2. Job Control (see Chapter 7 [Job Control], page 108) is enabled by default. When job control is in effect, Bash ignores the keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

  3. Bash expand sand displays PS1 before reading the first line of a command, and expands and displays PS2 before reading the second and subsequent lines of a multi-line com- mand. Bash expands and displays PS0 after it reads a command but before executing it. See Section 6.9 [Controlling the Prompt], page 99, for a complete list of prompt string escape sequences.

  4. Bash executes the values of the set elements of the PROMPT_COMMAND array variable as commands before printing the primary prompt, $PS1 (see Section 5.2 [Bash Variables], page 74).

  5. Readline(seeChapter8[CommandLineEditing],page112)is used to read commands from the user’s terminal.

  6. Bash inspects the value of the ignore eof option to set -o instead of exiting immediately when it receives an EOF on its standard input when reading a command (see Section 4.3.1 [The Set Builtin], page 62).

  7. Command history (see Section 9.1 [Bash History Facilities], page 147) and history expansion (see Section 9.3 [History Interaction], page 149) are enabled by default. Bash will save the command history to the file named by $HISTFILE when a shell with history enabled exits.

  8. Alias expansion (see Section 6.6 [Aliases], page 95) is performed by default.

  9. In the absence of any traps,Bash ignores SIGTERM(seeSection3.7.6[Signals],page42).

  10. In the absence of any traps, SIGINT is caught and handled (see Section 3.7.6 [Signals],

    page 42). SIGINT will interrupt some shell builtins.

  11. An interactive login shell sends a SIGHUP to all jobs on exit if the huponexit shell option has been enabled (see Section 3.7.6 [Signals], page 42).

  12. The -n invocation option is ignored, and ‘set -n’ has no effect (see Section 4.3.1 [The Set Builtin], page 62).

  13. Bash will check for mail periodically, depending on the values of the MAIL, MAILPATH, and MAILCHECK shell variables (see Section 5.2 [Bash Variables], page 74).

  14. Expansion errors due to references to unbound shell variables after ‘set -u’ has been enabled will not cause the shell to exit (see Section 4.3.1 [The Set Builtin], page 62).

  15. The shell will not exit on expansion errors caused by var being unset or null in ${var:?word} expansions (see Section 3.5.3 [Shell Parameter Expansion], page 25).

  16. Redirection errors encountered by shell builtins will not cause the shell to exit.

  17. When running in posix mode, a special builtin returning an error status will not cause the shell to exit (see Section 6.11 [Bash POSIX Mode], page 102).

  18. A failed exec will not cause the shell to exit (see Section 4.1 [Bourne Shell Builtins], page 44).

  19. Parser syntax errors will not cause the shell to exit.

  20. Simple spelling correction for directory arguments to the cd builtin is enabled by default (see the description of the cdspell option to the shopt builtin in Section 4.3.2 [The Shopt Builtin], page 66).

  21. The shell will check the value of the TMOUT variable and exit if a command is not read within the specified number of seconds after printing $PS1 (see Section 5.2 [Bash Variables], page 74).

7.1 Job Control

Job control refers to the ability to selectively stop (suspend) the execution of processes and continue (resume) their execution at a later point. A user typically employs this facility via an interactive interface supplied jointly by the operating system kernel’s terminal driver and Bash.

The shell associates a job with each pipeline. It keeps a table of currently executing jobs, which may be listed with the jobs command. When Bash starts a job asynchronously, it prints a line that looks like:

[1] 25647

indicating that this job is job number 1 and that the process id of the last process in the pipeline associated with this job is 25647. All of the processes in a single pipeline are members of the same job. Bash uses the job abstraction as the basis for job control.

To facilitate the implementation of the user interface to job control, the operating system maintains the notion of a current terminal process group id. Members of this process group (processes whose process group id is equal to the current terminal process group id) receive keyboard-generated signals such as SIGINT. These processes are said to be in the foreground. Background processes are those whose process group id differs from the terminal’s; such processes are immune to keyboard-generated signals. Only foreground processes are allowed to read from or, if the user so specifies with stty tostop, write to the terminal. Background processes which attempt to read from (write to when stty tostop is in effect) the terminal are sent a SIGTTIN (SIGTTOU) signal by the kernel’s terminal driver, which, unless caught, suspends the process.

If the operating system on which Bash is running supports job control, Bash contains facilities to use it. Typing the suspend character (typically ‘^Z’, Control-Z) while a process is running causes that process to be stopped and returns control to Bash. Typing the delayed suspend character (typically ‘^Y’, Control-Y) causes the process to be stopped when it attempts to read input from the terminal, and control to be returned to Bash. The user then manipulates the state of this job, using the bg command to continue it in the background, the fg command to continue it in the foreground, or the kill command to kill it. A ‘^Z’ takes effect immediately, and has the additional side effect of causing pending output and typeahead to be discarded.

8.2.5 Searching for Commands in the History

Readline provides commands for searching through the command history (see Section 9.1 [Bash History Facilities], page 147) for lines containing a specified string. There are two search modes: incremental and non-incremental.history

9.1 Bash History Facilities

When the -o history option to the set builtin is enabled (see Section 4.3.1 [The Set Builtin], page 62), the shell provides access to the command history, the list of commands previously typed. The value of the HISTSIZE shell variable is used as the number of com- mands to save in a history list. The text of the last $HISTSIZE commands (default 500) is saved. The shell stores each command in the history list prior to parameter and vari- able expansion but after history expansion is performed, subject to the values of the shell variables HISTIGNORE and HISTCONTROL.

When the shell starts up, the history is initialized from the file named by the HISTFILE variable (default ~/.bash_history). The file named by the value of HISTFILE is truncated, if necessary, to contain no more than the number of lines specified by the value of the HISTFILESIZE variable. When a shell with history enabled exits, the last $HISTSIZE lines are copied from the history list to the file named by $HISTFILE. If the histappend shell option is set (see Section 4.2 [Bash Builtins], page 51), the lines are appended to the history file, otherwise the history file is overwritten. If HISTFILE is unset, or if the history file is unwritable, the history is not saved. After saving the history, the history file is truncated to contain no more than $HISTFILESIZE lines. If HISTFILESIZE is unset, or set to null, a non-numeric value, or a numeric value less than zero, the history file is not truncated.

If the HISTTIMEFORMAT is set, the time stamp information associated with each history entry is written to the history file, marked with the history comment character. When the history file is read, lines beginning with the history comment character followed immediately by a digit are interpreted as timestamps for the following history entry.

The builtin command fc may be used to list or edit and re-execute a portion of the history list. The history builtin may be used to display or modify the history list and manipulate the history file. When using command-line editing, search commands are available in each editing mode that provide access to the history list (see Section 8.4.2 [Commands For History], page 129).

The shell allows control over which commands are saved on the history list. The HISTCONTROL and HISTIGNORE variables may be set to cause the shell to save only a subset of the commands entered. The cmdhist shell option, if enabled, causes the shell to attempt to save each line of a multi-line command in the same history entry, adding semicolons where necessary to preserve syntactic correctness. The lithist shell option causes the shell to save the command with embedded newlines instead of semicolons. The shopt builtin is used to set these options. See Section 4.3.2 [The Shopt Builtin], page 66, for a description of shopt.

밑줄 모음

  • Redirection

    The following redirection operators may precede or appear anywhere within a simple command or may follow a command. Redirections are processed in the order they appear, from left to right.

  • Redirecting input

    <’, the redirection refers to the standard input
    the standard input (file descriptor 0) if n is not specified

  • Redirecting output

    ‘>’, the redirection refers to the standard output
    the standard input (file descriptor 0) if n is not specified

  • Appending Redirected Output

    If the file does not exist it is created.

  • Here Documents

    No parameter and variable expansion, command substitution, arithmetic expansion, or filename expansion is performed on word. If any part of word is quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence \newline is ignored, and ‘\’ must be used to quote the characters ‘\’, ‘$’, and ‘‘’

  • Simple Command Expansion

    • When a simple command is executed, the shell performs the following expansions, assign- ments, and redirections, from left to right, in the following order.

      1. The words that the parser has marked as variable assignments (those preceding the command name) and redirections are saved for later processing.
      2. The words that are not variable assignments or redirections are expanded (see Section 3.5 [Shell Expansions], page 22). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments.
      3. Redirections are performed as described above(seeSection3.6[Redirections],page35).
      4. The text after the ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable.
    • A redirection error causes the command to exit with a non-zero status.

    • the exit status of the command is the exit status of the last command substitution performed. If there were no command substitutions, the command exits with a status of zero.

  • Command Search and Execution

  1. If the command name contains no slashes, the shell attempts to locate it.If there exists a shell function by that name, that function is invoked as described in Section 3.3 [Shell Functions], page 18.
  2. If the name does not match a function, the shell searches for it in the list of shell builtins. If a match is found, that builtin is invoked.
  3. If the name is neither a shell function nor a builtin, and contains no slashes, Bash searches each element of $PATH for a directory containing an executable file by that name. Bash uses a hash table to remember the full pathnames of executable files to avoid multiple PATH searches (see the description of hash in Section 4.1 [Bourne Shell Builtins], page 44). A full search of the directories in $PATH is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell searches for a defined shell function named command_not_found_handle. If that function exists, it is invoked in a separate execution environment with the original command and the original command’s arguments as its arguments, and the function’s exit status becomes the exit status of that subshell. If that function is not defined, the shell prints an error message and returns an exit status of 127.
  4. If the search is successful, or if the command name contains one or more slashes, the shell executes the named program in a separate execution environment. Argument 0 is set to the name given, and the remaining arguments to the command are set to the arguments supplied, if any.
  5. If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell script and the shell executes it as described in Section 3.8 [Shell Scripts], page 42.
  6. If the command was not begun asynchronously, the shell waits for the command to complete and collects its exit status.
  • Environment

    The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments, as described in Section 3.4 [Shell Parameters], page 20. These assignment statements affect only the environment seen by that command.

  • Exit Status

    • The exit status of an executed command is the value returned by the waitpid system call or equivalent function. Exit statuses fall between 0 and 255,
    • When a command terminates on a fatal signal whose number is N, Bash uses the value 128+N as the exit status.
  • Signals

    • When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT.
    • The shell exits by default upon receipt of a SIGHUP
  • Readline

    • Readline provides commands for searching through the command history
  • history

    • When the shell starts up, the history is initialized from the file named by the HISTFILE variable (default ~/.bash_history)

정리

작업중 - 2021.10.24

Reference

GNU Bash manual

profile
🏃🏾

0개의 댓글