📄 abs-book.sgml
字号:
script.</para> <para><token>#!</token> can be omitted if the script consists only of a set of generic system commands, using no internal shell directives. The second example, above, requires the initial <token>#!</token>, since the variable assignment line, <userinput>lines=50</userinput>, uses a shell-specific construct. Note again that <userinput>#!/bin/sh</userinput> invokes the default shell interpreter, which defaults to <filename>/bin/bash</filename> on a Linux machine.</para> <tip> <para>This tutorial encourages a modular approach to constructing a script. Make note of and collect <quote>boilerplate</quote> code snippets that might be useful in future scripts. Eventually you can build quite an extensive library of nifty routines. As an example, the following script prolog tests whether the script has been invoked with the correct number of parameters.</para> <para><programlisting>E_WRONG_ARGS=65script_parameters="-a -h -m -z"# -a = all, -h = help, etc.if [ $# -ne $Number_of_expected_args ]then echo "Usage: `basename $0` $script_parameters" # `basename $0` is the script's filename. exit $E_WRONG_ARGSfi</programlisting> </para> <para>Many times, you will write a script that carries out one particular task. The first script in this chapter is an example of this. Later, it might occur to you to generalize the script to do other, similar tasks. Replacing the literal (<quote>hard-wired</quote>) constants by variables is a step in that direction, as is replacing repetitive code blocks by <link linkend="functionref">functions</link>.</para> </tip> <sect1 id="invoking"> <title>Invoking the script</title> <para>Having written the script, you can invoke it by <userinput>sh scriptname</userinput>, <footnote><para>Caution: invoking a Bash script by <userinput>sh scriptname</userinput> turns off Bash-specific extensions, and the script may therefore fail to execute.</para></footnote> or alternatively <userinput>bash scriptname</userinput>. (Not recommended is using <userinput>sh <scriptname</userinput>, since this effectively disables reading from <filename>stdin</filename> within the script.) Much more convenient is to make the script itself directly executable with a <link linkend="chmodref">chmod</link>. <variablelist> <varlistentry> <term>Either:</term> <listitem> <para><userinput>chmod 555 scriptname</userinput> (gives everyone read/execute permission) <footnote><para>A script needs <emphasis>read</emphasis>, as well as execute permission for it to run, since the shell needs to be able to read it.</para></footnote> </para> </listitem> </varlistentry> <varlistentry> <term>or</term> <listitem> <para><userinput>chmod +rx scriptname</userinput> (gives everyone read/execute permission)</para> <para><userinput>chmod u+rx scriptname</userinput> (gives only the script owner read/execute permission)</para> </listitem> </varlistentry> </variablelist> </para> <para>Having made the script executable, you may now test it by <userinput>./scriptname</userinput>. <footnote><para>Why not simply invoke the script with <userinput>scriptname</userinput>? If the directory you are in (<link linkend="pwdref">$PWD</link>) is where <emphasis>scriptname</emphasis> is located, why doesn't this work? This fails because, for security reasons, the current directory is not by default included in a user's <link linkend="pathref">$PATH</link>. It is therefore necessary to explicitly invoke the script in the current directory with a <userinput>./scriptname</userinput>.</para></footnote> If it begins with a <quote>sha-bang</quote> line, invoking the script calls the correct command interpreter to run it.</para> <para>As a final step, after testing and debugging, you would likely want to move it to <filename class="directory">/usr/local/bin</filename> (as root, of course), to make the script available to yourself and all other users as a system-wide executable. The script could then be invoked by simply typing <command>scriptname</command> <keycap>[ENTER]</keycap> from the command line.</para> </sect1> <!-- Invoking the script --> <sect1 id="prelimexer"> <title>Preliminary Exercises</title> <orderedlist> <listitem> <para>System administrators often write scripts to automate common tasks. Give several instances where such scripts would be useful.</para> </listitem> <listitem> <para>Write a script that upon invocation shows the <link linkend="dateref">time and date</link>, <link linkend="whoref">lists all logged-in users</link>, and gives the system <link linkend="uptimeref">uptime</link>. The script then <link linkend="ioredirref">saves this information</link> to a logfile.</para> </listitem> </orderedlist> </sect1> <!-- Preliminary Exercises --> </chapter> <!-- Starting Off With a Sha-Bang --> </part> <!-- Part 1 (Introduction) --> <part label="Part 2" id="part2"> <title>Basics</title> <chapter id="special-chars"> <title>Special Characters</title> <variablelist id="scharlist"> <title><anchor id="scharlist1">Special Characters Found In Scripts and Elsewhere</title> <varlistentry><term><token>#</token></term> <indexterm> <primary>#</primary> </indexterm> <indexterm> <primary>special character</primary> <secondary>#</secondary> </indexterm> <indexterm> <primary>comment</primary> </indexterm> <listitem> <formalpara><title>Comments</title> <para>Lines beginning with a <token>#</token> (<link linkend="magnumref">with the exception of <token>#!</token></link>) are comments.</para> </formalpara> <para><programlisting># This line is a comment.</programlisting></para> <para>Comments may also occur following the end of a command.</para> <para><programlisting>echo "A comment will follow." # Comment here.# ^ Note whitespace before #</programlisting></para> <para>Comments may also follow <link linkend="whitespaceref">whitespace</link> at the beginning of a line.</para> <para><programlisting> # A tab precedes this comment.</programlisting></para> <caution><para>A command may not follow a comment on the same line. There is no method of terminating the comment, in order for <quote>live code</quote> to begin on the same line. Use a new line for the next command.</para></caution> <note><para>Of course, an escaped <token>#</token> in an <command>echo</command> statement does <emphasis>not</emphasis> begin a comment. Likewise, a <token>#</token> appears in <link linkend="psub2">certain parameter substitution constructs</link> and in <link linkend="numconstants"> numerical constant expressions</link>. <programlisting>echo "The # here does not begin a comment."echo 'The # here does not begin a comment.'echo The \# here does not begin a comment.echo The # here begins a comment.echo ${PATH#*:} # Parameter substitution, not a comment.echo $(( 2#101011 )) # Base conversion, not a comment.# Thanks, S.C.</programlisting> The standard <link linkend="quotingref">quoting and escape</link> characters (" ' \) escape the #. </para></note> <para>Certain <link linkend="psorex1">pattern matching operations</link> also use the <token>#</token>.</para> </listitem> </varlistentry> <varlistentry><term><token>;</token></term> <indexterm> <primary>;</primary> </indexterm> <indexterm> <primary>special character</primary> <secondary>;</secondary> </indexterm> <indexterm> <primary>separator</primary> </indexterm> <listitem> <formalpara><title>Command separator [semicolon]</title> <para>Permits putting two or more commands on the same line.</para> </formalpara> <para> <programlisting>echo hello; echo thereif [ -x "$filename" ]; then # Note that "if" and "then" need separation. # Why? echo "File $filename exists."; cp $filename $filename.bakelse echo "File $filename not found."; touch $filenamefi; echo "File test complete."</programlisting></para> <para>Note that the <quote><token>;</token></quote> sometimes needs to be <link linkend="escp">escaped</link>.</para> </listitem> </varlistentry> <varlistentry><term><token>;;</token></term> <indexterm> <primary>;;</primary> </indexterm> <indexterm> <primary>special character</primary> <secondary>case</secondary> </indexterm> <indexterm> <primary>;;</primary> </indexterm> <listitem> <formalpara><title>Terminator in a <link linkend="caseesac1">case</link> option [double semicolon]</title> <para><anchor id="doublesemicolon"></para> </formalpara> <para><programlisting>case "$variable" inabc) echo "\$variable = abc" ;;xyz) echo "\$variable = xyz" ;;esac</programlisting></para> </listitem> </varlistentry> <varlistentry><term><token>.</token></term> <indexterm> <primary>.</primary> </indexterm> <indexterm> <primary>special character</primary> <secondary>.</secondary> </indexterm> <indexterm> <primary>dot command</primary> </indexterm> <indexterm> <primary>source</primary> </indexterm> <listitem> <para><anchor id="dotref"></para> <formalpara><title><quote>dot</quote> command [period]</title> <para>Equivalent to <link linkend="sourceref">source</link> (see <xref linkend="ex38">). This is a bash <link linkend="builtinref">builtin</link>.</para> </formalpara> </listitem> </varlistentry> <varlistentry><term><token>.</token></term> <indexterm> <primary>.</primary> </indexterm> <indexterm> <primary>special character</primary> <secondary>.</secondary> </indexterm> <indexterm> <primary>filename</primary> </indexterm> <indexterm> <primary>part of a filename</primary> </indexterm> <listitem> <formalpara><title><quote>dot</quote>, as a component of a filename</title> <para>When working with filenames, a dot is the prefix of a <quote>hidden</quote> file, a file that an <link linkend="lsref">ls</link> will not normally show. <screen><prompt>bash$ </prompt><userinput>touch .hidden-file</userinput><prompt>bash$ </prompt><userinput>ls -l</userinput> <computeroutput>total 10 -rw-r--r-- 1 bozo 4034 Jul 18 22:04 data1.addressbook -rw-r--r-- 1 bozo 4602 May 25 13:58 data1.addressbook.bak -rw-r--r-- 1 bozo 877 Dec 17 2000 employment.addressbook</computeroutput><prompt>bash$ </prompt><userinput>ls -al</userinput> <computeroutput>total 14 drwxrwxr-x 2 bozo bozo 1024 Aug 29 20:54 ./ drwx------ 52 bozo bozo 3072 Aug 29 20:51 ../ -rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 data1.addressbook -rw-r--r-- 1 bozo bozo 4602 May 25 13:58 data1.addressbook.bak -rw-r--r-- 1 bozo bozo 877 Dec 17 2000 employment.addressbook -rw-rw-r-- 1 bozo bozo 0 Aug 29 20:54 .hidden-file</computeroutput> </screen> </para> </formalpara> <para>When considering directory names, <emphasis>a single dot</emphasis> represents the current working directory, and <emphasis>two dots</emphasis> denote the parent directory.</para> <para> <screen><prompt>bash$ </prompt><userinput>pwd</userinput><computeroutput>/home/bozo/projects</computeroutput><prompt>bash$ </prompt><userinput>cd .</userinput><prompt>bash$ </prompt><userinput>pwd</userinput><computeroutput>/home/bozo/projects</computeroutput><prompt>bash$ </prompt><userinput>cd ..</userinput><prompt>bash$ </prompt><userinput>pwd</userinput><computeroutput>/home/bozo/</computeroutput> </screen> </para> <para>The <emphasis>dot</emphasis> often appears as the destination (directory) of a file movement command.</para> <para> <screen><prompt>bash$ </prompt><userinput>cp /home/bozo/current_work/junk/* .</userinput> </screen> </para> </listitem> </varlistentry>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -