建立并且运行一个脚本[z]

本文介绍了如何编写并运行Bash脚本,包括脚本的基本结构、执行方式、调试技巧等内容。学习者将掌握如何创建简单脚本、设置权限、加入注释及调试脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

From:xiaowang.net/bgb-cn/ch02.html#sect_02_01_03

摘要

经过学习本章节,你将能够:

  • 写简单的脚本

  • 定义shell类型来运行脚本

  • 在脚本中加入注释

  • 改变脚本的权限

  • 执行并且调试脚本

2.1. 建立并且运行一个脚本

2.1.1. 编写与命名

一个shell脚本是你重复使用的命令序列。这个序列通常是通过在命令行输入整个脚本的命令来执行的。或者,你可以使用cron工具来使脚本自动执行任务。脚本的另外一个用法是在UNIX的启动和关闭过程中定义在init脚本中的守护程序和服务的操作。

要建立一个shell脚本,在你的编辑器中打开一个新的空白文件。任何文本编辑器就可以:vimemacsgeditdtpad都可以。可能你会选择一个高级的编辑器比如vim 或者 emacs,因为它们可以设置来高亮语法来帮助初学者避免很多经常犯的错误,比如忘记括号和冒号。

把UNIX命令放在一个新的空白文件里,就象在命令行输入命令。就像先前的讨论(参阅第 1.3 节 “执行命令”),命令可以作为shell函数,shell组成部分,UNIX命令和其他脚本。

为你的脚本起一个合理的名字来提醒自己脚本的作用。确定你的脚本的名字和已经存在的命令是没有冲突的。为了保证不会引起混乱,脚本名字经常以.sh结尾;尽管如此,还是有可能你选择的脚本名字已经和系统中原来的是相同的。使用whichwhereis和一些其他命令来查找程序的文件的信息:

which -a script_name

whereis script_name

locate script_name

2.1.2. script1.sh

在本例子中我们使用bash内建命令 echo 在此任务运行建立输出之前来通知用户将发生什么。强烈建议告知用户脚本的用途,因为本脚本什么事都不干防止用户变得过于紧张。我们会在第 8 章 编写交互脚本第八章继续如何通知用户。

图 2.1. script1.sh

Example script using statements like

正好自己写一下脚本。建立一个目录 ~/scripts 来存放你的脚本将会是个好主意。把此目录添加到 PATH 变量中:

export PATH="$PATH:~/scripts"

如果你才开始使用Bash,最好使用一个给不同结构以不同颜色的文本编辑器。vimgvim(x)emacskwrite和许多其他支持语法高亮的编辑器;详细请察看编辑器的文档。

[注意]不同的提示符

本教程的提示符的改变都依赖作者的心情。相对于标准的$提示符他更接近之际情况。唯一的约定就是,root提示符以#结尾。

2.1.3. 执行脚本

为了能使当前用户运行脚本,它应该有可执行权限。在设置权限时,检查你是否得到你想要得权限。完成后脚本就可以象其他命令一样运行:

willy:~/scripts> chmod u+x script1.sh

willy:~/scripts> ls -l script1.sh
-rwxrw-r--    1 willy	willy		456 Dec 24 17:11 script1.sh

willy:~> script1.sh
The script starts now.
Hi, willy!

I will now fetch you a list of connected users:

  3:38pm  up 18 days,  5:37,  4 users,  load average: 0.12, 0.22, 0.15
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT
root     tty2     -                Sat 2pm  4:25m  0.24s  0.05s  -bash
willy	 :0       -                Sat 2pm   ?     0.00s   ?     -
willy    pts/3    -                Sat 2pm  3:33m 36.39s 36.39s  BitchX willy ir
willy    pts/2    -                Sat 2pm  3:33m  0.13s  0.06s  /usr/bin/screen

I'm setting two variables now.
This is a string: black
And this is a number: 9

I'm giving you back your prompt now.

willy:~/scripts> echo $COLOUR

willy:~/scripts> echo $VALUE

willy:~/scripts>

这是执行脚本最普通的方法。在子shell中一般都是这么执行脚本。建立在子shell中的变量,函数和别名等只有子shell使用。当那个shell退出,父shell重新得到控制的时候,所有的东西都被清空,脚本对shell状态所作的改变耶全部清除。

如果你没有把 scripts的目录放到PATH里面,当前目录也不在PATH变量中,那么你可以这样来执行脚本:

./script_name.sh

脚本也可以被明确地指定shell执行,不过通常我们只有在想得到特殊的行为时候才这样做,比如脚本是否能在另外一个shell里面工作或者打印调试的信息:

rbash script_name.sh

sh script_name.sh

bash -x script_name.sh

特定的shell会成为当前shell子shell来运行脚本。当你想以特殊的选项或者以脚本没有指定的特殊条件来启动脚本时候可以这么做。

如果你想在当前脚本执行脚本而不想启动一个新的shell,你可以使用source

source script_name.sh

[提示]source = .

Bash内建命令 source 是和Bourne shell的 . (dot) 命令具有相同含义

这里脚本不需要可执行权限。命令在当前shell力执行,所以任何对环境的改变,将在脚本结束时同样起作用:

willy:~/scripts> source script1.sh
--output ommitted--

willy:~/scripts> echo $VALUE
9

willy:~/scripts>

  

2.2. 脚本基础

2.2.1. 哪个Shell来执行脚本?

当在子shell运行脚本时,你应该定义哪个shell来运行脚本,你编写的脚本的shell类型可能不是你系统默认的,所以用错误的shell来运行你输入的命令可能最终出错。

第一行决定了启动的shell,第一行的开始2个字符应该是#!,然后紧跟解释后面命令的shell的路径。空白行也被认为是一行,所以不要让你的脚本以空白行开始。

出于本教程的考虑,所有的脚本都这样开头:

#!/bin/bash

和先前提到过的一样,这样表明Bash可以在 /bin 里面找到。

2.2.2. 加入注释

你应该知道事实上你不会阅读你自己脚本的唯一的一个人。很多用户和系统管理员运行别人编写的脚本。如果他们想知道你是如何做到的,注释能很好的提醒读者。

注释也同样让你自己更方便。你一定阅读了很多帮助页面通过脚本中的一些命令来得到特定的结果。如果不对脚本加上注释,几个星期或者几个月后你需要更改你的脚本,你会忘记脚本做了些什么事,你怎么做的和为什么要这么做。

script1.sh 例子复制到 commented-script1.sh,编辑后反映了脚本的行为。在#后面的行被忽略而且只能在打开脚本时才能看到:

#!/bin/bash
# This script clears the terminal, displays a greeting and gives information
# about currently connected users.  The two example variables are set and displayed.

clear				# clear terminal window

echo "The script starts now."

echo "Hi, $USER!"		# dollar sign is used to get content of variable
echo

echo "I will now fetch you a list of connected users:"
echo							
w				# show who is logged on and
echo				# what they are doing

echo "I'm setting two variables now."
COLOUR="black"					# set a local shell variable
VALUE="9"					# set a local shell variable
echo "This is a string: $COLOUR"		# display content of variable 
echo "And this is a number: $VALUE"		# display content of variable
echo

echo "I'm giving you back your prompt now."
echo

在一个良好的脚本中,第一行经常注明要完成的任务。然后为了明确每一大块命令将被加上注释。作为一个例子,Linux的初始脚本,在你系统里的 init.d目录下,为了能让每个使用Linux的人读取和更改它,通常都作了良好的注释。


  

2.3. 调试Bash脚本

2.3.1. 调试整个脚本

当一些事情不能按照计划进行,你需要确定到底是什么导致了脚本运行失败。Bash提供了大量的调试特性。最通常的做法是使用 -x 选项来启动子shell,这将让整个脚本在调试模式下进行。每个命令和他附加参数的信息会在执行之前被展开并且送到标准输出打印。

以下是脚本 commented-script1.sh 在调试模式下运行。再次注意在脚本的输出中注释是不可见的。

willy:~/scripts> bash -x script1.sh
+ clear

+ echo 'The script starts now.'
The script starts now.
+ echo 'Hi, willy!'
Hi, willy!
+ echo

+ echo 'I will now fetch you a list of connected users:'
I will now fetch you a list of connected users:
+ echo

+ w
  4:50pm  up 18 days,  6:49,  4 users,  load average: 0.58, 0.62, 0.40
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT
root     tty2     -                Sat 2pm  5:36m  0.24s  0.05s  -bash
willy	 :0       -                Sat 2pm   ?     0.00s   ?     -
willy	 pts/3    -                Sat 2pm 43:13  36.82s 36.82s  BitchX willy ir
willy    pts/2    -                Sat 2pm 43:13   0.13s  0.06s  /usr/bin/screen
+ echo

+ echo 'I'\''m setting two variables now.'
I'm setting two variables now.
+ COLOUR=black
+ VALUE=9
+ echo 'This is a string: '
This is a string:
+ echo 'And this is a number: '
And this is a number:
+ echo

+ echo 'I'\''m giving you back your prompt now.'
I'm giving you back your prompt now.
+ echo
[注意]未来bash的特性

现在有一个全新的Bash调式工具出现在SourceForge。然而现在,你需要一个已经打过补丁的Bash-2.05。新的特性可能会在bash-3.0中出现。

2.3.2. 调试部分脚本

使用bash内建命令 set 可以让那些确定没有错误的部分以正常模式运行,而只对有错误的部分显示其debug信息。比如我们不确定在 commented-script1.sh 里面 w 命令会做些什么,那么我们可以把它象这样包含起来:

set -x			# activate debugging from here
w
set +x			# stop debugging from here

输出看来就像这样:

willy: ~/scripts> script1.sh
The script starts now.
Hi, willy!

I will now fetch you a list of connected users:

+ w
  5:00pm  up 18 days,  7:00,  4 users,  load average: 0.79, 0.39, 0.33
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU  WHAT
root     tty2     -                Sat 2pm  5:47m  0.24s  0.05s  -bash
willy    :0       -                Sat 2pm   ?     0.00s   ?     -
willy    pts/3    -                Sat 2pm 54:02  36.88s 36.88s  BitchX willyke
willy    pts/2    -                Sat 2pm 54:02   0.13s  0.06s  /usr/bin/screen
+ set +x

I'm setting two variables now.
This is a string:
And this is a number:

I'm giving you back your prompt now.

willy: ~/scripts>

你可以在同样的脚本里多次打开关闭调试模式。

下表给出了其他有用的bash选项概貌:

表 2.1. 设置调试选项概览

短符号长符号结果
set -fset -o noglob禁止特殊字符用于文件名扩展。
set -vset -o verbose打印读入shell的输入行。
set -xset -o xtrace执行命令之前打印命令。

横线用来激活一个shell选项,再使用一次将解除。不要搞错了!

以下例子,我们在命令行里面证明这些选项:

willy:~/scripts> set -v

willy:~/scripts> ls
ls 
commented-scripts.sh	script1.sh

willy:~/scripts> set +v
set +v

willy:~/scripts> ls *
commented-scripts.sh    script1.sh

willy:~/scripts> set -f

willy:~/scripts> ls *
ls: *: No such file or directory

willy:~/scripts> touch *

willy:~/scripts> ls
*   commented-scripts.sh    script1.sh

willy:~/scripts> rm *

willy:~/scripts> ls
commented-scripts.sh    script1.sh

或者,这些模式也可以在脚本里面指定,只需在第一行shell的声明中加入需要的选项。选项可以叠加,和通常UNIX命令一样:

#!/bin/bash -xv

每当你找到脚本中的错误部分,你可以在每个你不确定的命令之前增加 echo语句,这样你就会明确的看到哪里或者为什么脚本没有正常工作。在 commented-script1.sh例子中,可以这么做,依然假设显示用户这部分出了问题:

echo "debug message: now attempting to start w command"; w

在更高级的脚本中, echo 可以插入到在不同的阶段显示变量表,因此可以检查到错误:

echo "Variable VARNAME is now set to $VARNAME."
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值