Linux - Basic Scripting

Part 1: Shell Scripts in a Nutshell

shell script is a file of executable commands that has been stored in a text file. When the file is run, each command is executed. Shell scripts have access to all the commands of the shell, including logic. A script can therefore test for the presence of a file or look for particular output and change its behavior accordingly. You can build scripts to automate repetitive parts of your work, which frees your time and ensures consistency each time you use the script. For instance, if you run the same five commands every day, you can turn them into a shell script that reduces your work to one command.

A script can be as simple as one command:

echo “Hello, World!”

The script, test.sh, consists of just one line that prints the string “Hello, World!” to the console.

Running a script can be done either by passing it as an argument to your shell or by running it directly:

bob:tmp $ sh test.sh
Hello, World!
bob:tmp $ ./test.sh
-bash: ./test.sh: Permission denied
bob:tmp $ chmod +x ./test.sh
bob:tmp $ ./test.sh
Hello, World

In the example above, first, the script is run as an argument to the shell. Next, the script is run directly from the shell. It is rare to have the current directory in the binary search path ($PATH) so the name is prefixed with “./” to indicate it should be run out of the current directory.

The error “Permission denied” means that the script has not been marked as executable. A quick chmod later and the script works. chmod is used to change the permissions of a file, which will be explained in detail in a later chapter.

There are various shells with their own language syntax. Therefore, more complicated scripts will indicate a particular shell by specifying the absolute path to the interpreter as the first line, prefixed by “#!” as shown:

#!/bin/sh
echo “Hello, World!”

or

#!/bin/bash
echo “Hello, World!”

The two characters, “#!” are traditionally called the hash and the bang respectively, which leads to the shortened form of “shebang” when they’re used at the beginning of a script.

Incidentally, the shebang (or crunchbang) is used for traditional shell scripts and other text-based languages like Perl, Ruby, and Python. Any text file marked as executable will be run under the interpreter specified in the first line as long as the script is run directly. If the script is invoked directly as an argument to an interpreter, such as sh script or bash script, the given shell will be used no matter what’s in the shebang line.

It helps to become comfortable using a text editor before writing shell scripts, since you will need to create files in plain text. Traditional office tools like LibreOffice that output file formats containing formatting and other information are not appropriate for this task.

Part 2: Editing Shell Scripts

UNIX has many text editors, the merits of one over the other are often hotly debated. Two are specifically mentioned in the LPI Essentials syllabus: The GNU nano editor is a very simple editor well suited to editing small text files. The Visual Editor, vi, or its newer version, VI improved (vim), is a remarkably powerful editor but has a steep learning curve. We’ll focus on nano.

Type nano test.sh and you’ll see a screen similar to this:

Nano has few features to get in your way. You simply type with your keyboard, using the arrow keys to move around and the delete/backspace button to delete text. Along the bottom of the screen you can see some commands available to you, which are context sensitive and change depending on what you’re doing. If you’re directly on the Linux machine itself, as opposed to connecting over the network, you can also use the mouse to move the cursor and highlight text.

To get familiar with the editor, start typing out a simple shell script while inside nano:

Note that the bottom-left option is ^X Exit which means “press control and X to exit”. Press Ctrl and X together and the bottom will change:

At this point, you can exit the program without saving by pressing the N key, or save first by pressing Y to save. The default is to save the file with the current file name. You can press the Enter key to save and exit.

You will be back at the shell prompt after saving. Return to the editor. This time press Ctrl and O together to save your work without exiting the editor. The prompts are largely the same, except that you’re back in the editor.

This time use the arrow keys to move your cursor to the line that has “The time is”. Press Control and K twice to cut the last two lines to the copy buffer. Move your cursor to the remaining line and press Control and U once to paste the copy buffer to the current position. This makes the script echo the current time before greeting you and saved you needing to re-type the lines.

Other helpful commands you might need are:

Command Description
Ctrl + W search the document
Ctrl + W, then Control + R search and replace
Ctrl + G show all the commands possible
Ctrl + Y/V page up / down
Ctrl + C show the current position in the file and the file’s size

Part 3: Scripting Basics

You got your first taste of scripting earlier in this chapter where we introduced a very basic script that ran a single command. The script started with the shebang line, telling Linux that /bin/bash (which is Bash) is to be used to execute the script.

Other than running commands, there are 3 topics you must become familiar with:

  1. Variables, which hold temporary information in the script
  2. Conditionals, which let you do different things based on tests you write
  3. Loops, which let you do the same thing over and over

1. Variables

Variables are a key part of any programming language. A very simple use of variables is shown here:

#!/bin/bash

ANIMAL="penguin"
echo "My favorite animal is a $ANIMAL"

After the shebang line is a directive to assign some text to a variable. The variable name is ANIMAL and the equals sign assigns the string “penguin”. Think of a variable like a box in which you can store things. After executing this line, the box called “ANIMAL” contains the word “penguin”.

It is important that there are no spaces between the name of the variable, the equals sign, and the item to be assigned to the variable. If you have a space there, you will get an odd error such as “command not found”. Capitalizing the name of the variable is not necessary but it is a useful convention to separate variables from commands to be executed.

Next, the script echos a string to the console. The string contains the name of the variable preceded by a dollar sign. When the interpreter sees that dollar sign it recognizes that it will be substituting the contents of the variable, which is calledinterpolation. The output of the script is then “My favorite animal is a penguin”.

So remember this: To assign to a variable, just use the name of the variable. To access the contents of the variable, prefix it with a dollar sign. Here, we show a variable being assigned the contents of another variable!

#!/bin/bash

ANIMAL=penguin
SOMETHING=$ANIMAL
echo "My favorite animal is a $SOMETHING"

ANIMAL contains the string “penguin” (as there are no spaces, the alternative syntax without using quotes is shown). SOMETHING is then assigned the contents of ANIMAL (because ANIMAL has the dollar sign in front of it).

If you wanted, you could assign an interpolated string to a variable. This is quite common in larger scripts, as you can build up a larger command and execute it!

Another way to assign to a variable is to use the output of another command as the contents of the variable by enclosing the command in back ticks:

#!/bin/bash
CURRENT_DIRECTORY=`pwd`
echo "You are in $CURRENT_DIRECTORY"

This pattern is often used to process text. You might take text from one variable or an input file and pass it through another command like sed or awk to extract certain parts and keep the result in a variable.

It is possible to get input from the user of your script and assign it to a variable through the read command:

#!/bin/bash

echo -n "What is your name? "
read NAME
echo "Hello $NAME!"

Read can accept a string right from the keyboard or as part of command redirection like you learned in the last chapter.

There are some special variables in addition to the ones you set. You can pass arguments to your script:

#!/bin/bash
echo "Hello $1"

A dollar sign followed by a number N corresponds to the Nth argument passed to the script. If you call the example above with ./test.sh the output will be “Hello Linux”. The $0 variable contains the name of the script itself.

After a program runs, be it a binary or a script, it returns an exit code which is an integer between 0 and 255. You can test this through the $? variable to see if the previous command completed successfully.

bob:tmp $ grep -q root /etc/passwd
bob:tmp $ echo $?
0
bob:tmp $ grep -q slartibartfast /etc/passwd
bob:tmp $ echo $?
1

The grep command was used to look for a string within a file with the –q flag, which means “quiet”. Grep, while running in quiet mode, returns 0 if the string was found and 1 otherwise. This information can be used in a conditional to perform an action based on the output of another command.

Likewise you can set the exit code of your own script with the exit command:

#!/bin/bash
# Something bad happened!
exit 1

The example above shows a comment (#). Anything after the hash mark is ignored which can be used to help the programmer leave notes. The “exit 1” returns exit code 1 to the caller. This even works in the shell, if you run this script from the command line and then type “echo $?” you will see it returns 1.

By convention, an exit code of 0 means “everything is OK”. Exit codes greater than 0 mean some kind of error happened, which is specific to the program. Above you saw that grep uses 1 to mean the string was not found.

2. Conditionals

Now that you can look at and set variables, it is time to make your script do different functions based on tests, called branching. The if statement is the basic operator to implement branching.

A basic if statement looks like this:

if somecommand; then
  # do this if somecommand has an exit code of 0
fi

The next example will run “somecommand” (actually, everything up to the semicolon) and if the exit code is 0 then the contents up until the closing “fi” will be run. Using what you know about grep, you can now write a script that does different things based on the presence of a string in the password file:

#!/bin/bash

if grep -q root /etc/passwd; then
  echo root is in the password file
else
  echo root is missing from the password file
fi

From previous examples, you might remember that the exit code of grep is 0 if the string is found. The example above uses this in one line to print a message if root is in the password or a different message if it isn’t. The difference here is that instead of an “fi” to close off the if block, there’s an “else”. This lets you do one action if the condition is true, and another if the condition is false. The else block must still be closed with the fi keyword.

Other common tasks are to look for the presence of a file or directory and to compare strings and numbers. You might initialize a log file if it doesn’t exist, or compare the number of lines in a file to the last time you ran it. “If” is clearly the command to help here, but what command do you use to make the comparison?

The test command gives you easy access to comparison and file test operators. For example:

Command Description
test –f /dev/ttyS0 0 if the file exists
test ! –f /dev/ttyS0 0 if the file doesn’t exist
test –d /tmp 0 if the directory exists
test –x `which ls` substitute the location of ls then test if the user can execute
test 1 –eq 1 0 if numeric comparison succeeds
test ! 1 –eq 1 NOT – 0 if the comparison fails
test 1 –ne 1 Easier, test for numeric inequality
test “a” = “a” 0 if the string comparison succeeds
test “a” != “a” 0 if the strings are different
test 1 –eq 1 –o 2 –eq 2 -o is OR: either can be the same
test 1 –eq 1 –a 2 –eq 2 -a is AND: both must be the same

It is important to note that test looks at integer and string comparisons differently. 01 and 1 are the same by numeric comparison, but not by string comparison. You must always be careful to remember what kind of input you expect.

There are many more tests, such as –gt for greater than, ways to test if one file is newer than the other, and many more. Consult the test man page for more.

test is fairly verbose for a command that gets used so frequently, so there is an alias for it called ‘[‘ (left square bracket). If you enclose your conditions in square brackets, it’s the same as running test. So, these statements are identical.

if test –f /tmp/foo; then
if [ -f /tmp/foo]; then

While the latter form is most often used, it is important to understand that the square bracket is a command on its own that operates similarly to test except that it requires the closing square bracket.

“if” has a final form, that lets you do multiple comparisons at one time using “elif” (short for else if).

#!/bin/bash

if [ "$1" = "hello" ]; then
  echo "hello yourself"
elif [ "$1" = "goodbye" ]; then
  echo "nice to have met you"
  echo "I hope to see you again"
else
  echo "I didn‘t understand that"
fi

The code above compares the first argument passed to the script. If it is hello, the first block is executed. If not, the script checks to see if it is goodbye and echos a different message if so. Otherwise, a third message is sent. Note that the $1 variable is quoted and the string comparison operator is used instead of the numeric version (-eq).

The if/elif/else tests can become quite verbose and complicated. The casestatement provides a different way of making multiple tests easier.

#!/bin/bash

case "$1" in
hello|hi)
  echo "hello yourself"
  ;;
goodbye)
  echo "nice to have met you"
  echo "I hope to see you again"
  ;;
*)
  echo "I didn‘t understand that"
esac

The case statement starts off with a description of the expression being tested: case EXPRESSION in. The expression here is the quoted $1.

Next, each set of tests are executed as a pattern match terminated by a closing parenthesis. The previous example first looks for “hello” or “hi”; multiple options are separated by the vertical bar (|) which is an OR operator in many programming languages. Following that are the commands to be executed if the pattern returns true, which are terminated by two semicolons. The pattern repeats.

The * pattern is the same as an else because it matches anything. The behavior of the case statement is similar to the if/elif/else statement in that processing stops after the first match. If none of the other options matched the * ensures that the last one will match.

With a solid understanding of conditionals you can have your scripts take actions only if necessary.

3. Loops

Loops allow code to be executed repeatedly. They can be useful in numerous situations, such as when you want to run the same commands over each file in a directory, or repeat some action 100 times. There are two main loops in shell scripts: the for loop and the while loop.

For loops are used when you have a finite collection over which you want to iterate, such as a list of files, or a list of server names:

#!/bin/bash

SERVERS="servera serverb serverc"
for S in $SERVERS; do
  echo "Doing something to $S"
done

The script first sets a variable containing a space separated list of server names. The for statement then loops over the list of servers, each time it sets the S variable to the current server name. The choice of S was arbitrary, but note that the S has no dollar sign but the $SERVERS does, showing that $SERVERS will be expanded to the list of servers. The list does not have to be a variable. This example shows two more ways to pass a list.

#!/bin/bash

for NAME in Sean Jon Isaac David; do
  echo "Hello $NAME"
done

for S in *; do
  echo "Doing something to $S"
done

The first loop is functionally the same as the previous example, except that the list is passed to the for loop directly instead of using a variable. Using a variable helps the clarity of the script as someone can easily make changes to the variable rather than looking at a loop.

The second loop uses a * which is a file glob. This gets expanded by the shell to all the files in the current directory.

The other type of loop, a while loop, operates on a list of unknown size. Its job is to keep running and on each iteration perform a test to see if it should run another time. You can think of it as “while some condition is true, do stuff.”

#!/bin/bash

i=0
while [ $i -lt 10 ]; do
  echo $i
  i=$(( $i + 1))
done
echo “Done counting”

The example above shows a while loop that counts from 0 to 9. A counter variable, i, is initialized to 0. Then a while loop is run with the test being “is $i less than 10?” Note that the while loop uses the same notation as an if statement!

Within the while loop the current value of i is echoed and then 1 is added to it through the $(( arithmetic )) command and assigned back into i. Once i becomes 10 the while statement returns false and processing continues after the loop.

时间: 2024-11-10 11:20:06

Linux - Basic Scripting的相关文章

Linux Bash Scripting - Command Chaining & Command lists

# this is to show you how to execute a series of commands in one strike. $ clear; cd /; ls -l; echo "You are in $PWD"; echo "Time to go back home"; cd ~; # use semi colon between each command. # There is also command lists, which is fo

Linux basic(1)

Linux基础概念 一.终端       终端设备分为三种:物理终端,虚拟终端,模拟终端. 物理终端:直接连接主机的显示器和键盘设备.                 设备文件路径:/dev/console 虚拟终端:附加在物理终端之上以软件形式虚拟实现的终端.在虚拟终端中还包含有图形终端.                            图形终端:附加在物理终端之上以软件形式虚拟实现的终端,提供桌面环境.                                      设备文件

[linux basic]--线程

/************************************************************************* > File Name: thread1.c > Author: > Mail: > Created Time: 2016年03月26日 星期六 22时37分44秒 ************************************************************************/ #include<

一组Linux Shell Scripting小练习

# Linux shell将字符串分割成数组 result=$(facter | awk '/ipaddress/ && !/ipaddress_lo/ {print $1 " " $3}') array=($result) # 判断一个变量是否存在(不是判断是否为空) if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; f

Linux basic (2)

编程能力: 脚本编程 grep, sed(流编辑器), awk sed基本用法: sed: Stream EDitor 行编辑器 (全屏编辑器: vi) sed: 模式空间 默认不编辑原文件,仅对模式空间中的数据做处理:而后,处理结束后,将模式空间打印至屏幕: sed [options] 'AddressCommand' file ... -n: 静默模式,不再默认显示模式空间中的内容 -i: 直接修改原文件 -e SCRIPT -e SCRIPT:可以同时执行多个脚本 -f /PATH/TO/

[linux basic]基础--信号

线程->信号信号,是unix和linux系统响应某些条件而产生的一个事件.接收到该信号的进程会相应地采取一些行动.raise生成表示一个信号的产生catch捕获表示接受到一个信号的产生:信号是由于某些错误条件而产生,内存段冲突,浮点处理器错误或者非法指令等.它们由shell和终端处理器生成引起中断,可以作为进程见传递消息或修改行为的一种方式,明确地由一个进程发送给另一个进程.无论什么情况,它们的编程接口都是相同的,信号可以被生成,捕获,响应,忽略.signal.h====== sigabort

linux basic test

Linux 1◆ 提供连接 ? ? 2◆ connection baidu.com 3◆ vm tools install Reboot ? ? 原文地址:https://www.cnblogs.com/rhxuza1993/p/9855551.html

Linux Basic 6:vim及一些的Shell脚本

本周作业内容: 1.复制/etc/rc.d/rc.sysinit文件至/tmp目录,将/tmp/rc.sysinit文件中的以至少一个空白字符开头的行的行首加#: 2.复制/boot/grub/grub.conf至/tmp目录中,删除/tmp/grub.conf文件中的行首的空白字符: 3.删除/tmp/rc.sysinit文件中的以#开头,且后面跟了至少一个空白字符的行行的#和空白字符 4.为/tmp/grub.conf文件中前三行的行首加#号: 5.将/etc/yum.repos.d/Cen

linux basic

centos7 ip addr 查看网络连接及其状态 ip link 查看网络连接及其状态 ip –s link 查看统计信息. ---------------------------------- redhat5不能用ifconfig 和 ip 原因:ifconfig命令所在路径/sbin未包含在系统环境变量PATH中解决方法:1. 直接输入:/sbin/ifconfig2. 临时修改环境变量:在shell中输入   $export PATH = $PATH:/sbin   然后再输入ifco