1.进入命令行,CLI(command line interface),也叫Linux控制台
- 通过Linux控制台终端访问CLI
- Ctrl+Alt+F1~F7
注:tty:teletypewriter,指一台用于发送消息的机器
控制台的外观设置命令:setterm2.通过图形化的终端访问CLI
1. bash手册
1.1 熟悉DESCRIPTION部分的前两段可以学到很多技术行话
1.2 空格键:翻页
1.3 回车键:逐行查看2. Linux手册页的内容区域
- 1.可执行文件或shell命令
- 2.系统调用
- 3.库调用
- 4.特殊文件
- 5.文格式约定
- 6.游戏
- 7.概览、约定及杂项
- 8.超级用户和系统管理员命令
- 9.内核例程
- 查看所需的页面:man section# topic
- 查看内容简介:man 1 intro
- 另一个参考信息:info info
3.Linux文件系统
3.1 常见的目录名称
- / :虚拟目录的根目录
- /bin :二进制目录,存放许多用户级的GNU工具
- /boot:启动目录,存放启动文件
- /dev :设备目录,Linux在这里创建设备节点
- /etc :系统配置文件目录
- /home:主目录,Linux在这里创建用户目录
- /lib :库目录,存放系统和应用程序的库文件
- /media:媒体目录,可移动媒体设备的常用挂载点
- /mnt :挂载目录,另一个可移动媒体设备的常用挂载点
- /opt :可选目录,常用于存放第三方软件包和数据文件
- /proc:进程目录,存放现有硬件及当前进程的相关信息
- /root:root用户的主目录
- /sbin:系统二进制目录,存放许多GNU管理员级工具
- /run :运行目录,存放系统运作时的运行时数据
- /srv :服务目录,存放本地服务的相关文件
- /sys :系统目录,存放系统硬件信息的相关文件
- /tmp :临时目录,可以在该目录中创建和删除临时工作文件
- /usr :用户二进制目录,大量用户级的GNU工具和数据文件都存储在这里
- /var :可变目录,用以存放经常变化的文件,比如日志文件
3.2 文件和目录列表
- ls -F :区分文件和目录
- ls -a :显示隐藏目录
- ls -F -R :递归列出当前目录下包含的子目录中的文件
- ls -l :长列表格式输出,每行都包含了下述信息
文件类型,比如目录( d )、文件( - )、字符型文件( c )或块设备( b );
文件的权限(参见第6章);
文件的硬链接总数;
文件属主的用户名;
文件属组的组名;
文件的大小(以字节为单位);
文件的上次修改时间;
文件名或目录名;3.3 使用元字符通配符过滤文件
- ls -l scr[ai]pt :a或i
- ls -l f[a-i]ll :指定字符范围
- ls -l f[!a]ll :除了a
3.4 创建文件
- touch test_one :创建一个空文件,如果已经存在,则修改文件的创建时间
- touch -a test_one :改变文件创建时间
- ls -l --time=atime test_one :加粗文件创建时间
3.5 链接文件:指向文件真实位置的占位符
3.5.1 符号链接:指向虚拟结构目录中某个地方的另一个文件,彼此内容不同
- ln -s data_file s1_data_file :给data_file创建一个符号链接
- ls -l *data_file :查看该链接文件,可以看到大小不一样
- ls -i *data_file :查看两个文件的inode节点编号,可以看到不一样
3.5.2硬链接:会创建独立的虚拟文件,包含原始文件的信息和位置,本质上是同一个文件(必须在同一个媒体)
- ln code_file h1_code_file :创建一个硬链接
- ls -li *code_file :查看两个文件
3.6.删除文件
- rm -i fall :带提示的删除
- rm -f fall :强制删除
- rm -ri my_diir:删除目录中的文件,再删除目录本身
- rm -ri my_diir:递归删除目录中的文件,再删除目录本身
3.7 创建目录
- mkdir -p New_dir/Sub_dir/under_ir :同时创建多个目录及子目录用 -p参数
- tree New_dir :以树的形式查看目录结构
3.8 查看文件内容
- file my_file :查看文件或者目录类型
- cat -n test1 :显示文本文件数据,并加上行号
- cat -b test1 :只给有文本的加上行号
- cat -T test1 :不让制表符出现
- more test1 :显示文件内容,不过会在每一页后停下来
- less test1 :跟more差不多,但是更高级,支持方向键上下翻页
- tail -n 2 test1 :只显示最后两行的内容
- head -n 2 test1 :显示文件开头两行内容
1.监测程序
- ps :显示运行在当前控制台下的属于当前用户的进程
- ps -ef :显示所有进程的完整信息
其他参数- -A 显示所有进程
- -N 显示与指定参数不符的所有进程
- -a 显示除控制进程(session leader ① )和无终端进程外的所有进程
- -d 显示除控制进程外的所有进程
- -e 显示所有进程
- -C cmdlist 显示包含在 cmdlist 列表中的进程
- -G grplist 显示组ID在 grplist 列表中的进程
- -U userlist 显示属主的用户ID在 userlist 列表中的进程
- -g grplist 显示会话或组ID在 grplist 列表中的进程 ②
- -p pidlist 显示PID在 pidlist 列表中的进程
- -s sesslist 显示会话ID在 sesslist 列表中的进程
- -t ttylist 显示终端ID在 ttylist 列表中的进程
- -u userlist 显示有效用户ID在 userlist 列表中的进程
- -O format 显示默认的输出列以及 format 列表指定的特定列
- -o format 仅显示由 format 指定的列
- -n namelist 定义了 WCHAN 列显示的值
- -F 显示更多额外输出(相对 -f 参数而言)
- -M 显示进程的安全信息
- -c 显示进程的额外调度器信息
- -f 显示完整格式的输出
- -j 显示任务信息
- -l 显示长列表
F:内核分配给进程的系统标记
S:进程状态(O表示正在运行,S表示正在休眠,R表示可运行,正在等待运行,Z表示僵尸进程)- -y 不要显示进程标记(process flag,表明进程状态的标记)
- -Z 显示安全标签(security context) ① 信息
- -H 用层级格式来显示进程(树状,用来显示父进程)
- -w 采用宽输出模式,不限宽度显示
- -L 显示进程中的线程
- -V 显示 ps 命令的版本号
top :跟ps相似,不过它显示的是实时的
2.结束进程
- kill 3904 :给进程ID是3904的进程发送TERM(尽可能终止)信号
- kill -s HUP 3940 :给进程ID是3904的进程发送HUP(挂起)信号
- killall http* :结束以http开头的进程
3.检测磁盘空间
- mount :列出当前系统上挂载的设备列表
- mount -t vfat /dev/sdb1 /media/disk :手动将U盘/dev/sdb1挂载到/media/disk目录下
- umount /home/rich/mnt :卸载设备
- df -h :查看所有已挂载设备的的磁盘使用情况,-h用易读的方式显示
- du /mnt/hgfs :查看特定目录下的磁盘使用情况,不加参数表示当前目录
4.处理数据文件
- sort -n file :排序file文件,并把数字识别成数字
- sort -M file3 :按月份(3个字母)排序,常用于日志文件
- sort -t ‘:’ -k 3 -n /etc/passwd :对密码文件根据用户ID排序,-t指定区分键位置字符,-k排序其实位置
- grep three file :在file中搜索three文本
- grep -v three filre :在file文件中反向搜索three文本,即不包含three的行
- grep -C three filre :在file文件中反向搜索three文本,只输出有多少个行含有匹配模式
- grep -n three filre :在file文件中反向搜索three文本,仅输出行号
- grep -e t -e f file :如果要指定多个模式,-e指定每个模式
- grep [tf] file :使用正则表达式搜索包含字符t或者f的匹配
- gzip my* :通过通配符一次性批量压缩文件
- gzcat myprog.c.gz :查看压缩过的文本文件的内容
- gunzip myprog.c.gz :解压文件
- tar -cvf test.tar test/ test2/ :归档文件
- tar -tf test.tar :列出test.tar的内容
- tar -zxvf file.tgz :解压用gzip压缩过的文件
shell不单单是一种CLI,它是一个时刻都在运行的交互式程序
/bin/sh:用于那些在系统启动时使用的系统shell脚本
ps --forest:展示进程间的嵌套结构5.1 可通过命令行参数修改shell的启动方式
- -c string 从 string 中读取命令并进行处理
- -i 启动一个能够接收用户输入的交互shell
- -l 以登录shell的形式启动
- -r 启动一个受限shell,用户会被限制在默认目录中
- -s 从标准输入中读取命令
5.2 常用命令
- echo $BASH_SUBSHELL :查看子shell的个数
- sleep 10 :会话暂停10秒钟
- sleep 10& :sleep命令睡眠10秒钟放到后台运行
- jobs :显示当前运行在后台模式的所有用户进程(作业)
- coproc sleep 10 :在后天生成一个子shell,并把命令放到后台运行
- coproc My_job { sleep 10; } :给协程命名
5.3 理解shell的内建命令
5.3.1 外部命令:也叫文件系统命令,通常位于/bin、/usr/bin、/sbin或者/usr/sbin中
- which ps :用which命令找到外部ps命令
- type ps :跟上面一样
5.3.2内部命令:不需要使用子进程来执行,作为shell的组成部分存在
- type cd :查看cd是不是内部命令
- history :跟踪使用过的命令,保存在隐藏文件.bash_history中,位于用户主目录
!! :唤回并重用历史命令中最近的命令
history -a :强制将历史记录写入.bash_history
!20 :唤回历史命令中的第20条命令- alias :查看可用的别名
- alias ll=‘ls -alF’ :设置别名,不过仅在被定义的shell中才有效
bash shell用一个叫做环境变量的(enviroment variable)的特性来存储有关 shell会话 和 工作环境 的信息
6.1 全局/局部 环境变量
----全局环境变量对于shell会话和所有生成的字shell都是可见的
----局部变量则只对创建他们的shell可见
6.2设置用户定义变量
6.3 定位系统环境变量
当登入Linux系统启动一个bash shell时,默认情况下bash会在几个文件中查找命令,这些文件叫 启动文件 或 环境文件
- 查看、/etc目录下通用的bashrc文件
- 为用户提供一个定制自己的命令别名和私有脚本函数的地方
6.4 环境变量的持久化
6.5 数组变量
mytest=(one two three four five) :值放括号,值之间用空格隔开
echo ${mytest[2]} :引用单独的数组元素,索引值要用方括号
echo ${mytest[*]} :显示整个数组元素
mytest[2]=severn :可以改变索引位置的值
unset mytest[2] :删除相当于mytest[2]=""
linux安全系统的核心是用户账户。用户权限是通过创建用户时分配的用户ID(缩写为UID)
7.1 /etc/passwd文件
7.2 使用Linux组
组权限允许多个用户对系统中的对象(比如文件、目录或设备等)共享一组共用的权限,每个组都有唯一的GID和组名
7.3 理解文件权限
- 代表文件
d 代表目录
l 代表链接
c 代表字符型设备
b 代表块设备
n 代表网络设备
r 代表对象是可读的
w 代表对象是可写的
x 代表对象是可执行的
7.4 改变安全性设置
u 代表用户
g 代表组
o 代表其他
a 代表上述所有
X :如果对象是目录或者它已有执行权限,赋予执行权限。
s :运行时重新设置UID或GID。
t :保留文件或目录。
u :将权限设置为跟属主一样。
g :将权限设置为跟属组一样。
o :将权限设置为跟其他用户一样。
7.5 共享文件
h :左移一个字符。
j :下移一行(文本中的下一行)。
k :上移一行(文本中的上一行)。
l :右移一个字符。
PageDown (或Ctrl+F):下翻一屏。
PageUp (或Ctrl+B):上翻一屏。
G :移到缓冲区的最后一行。
num G :移动到缓冲区中的第 num 行。
gg :移到缓冲区的第一行。
w filename :将文件保存到另一个文件中
删除:x(取叉、错的意思):删除当前光标所在位置的字符
删除:dd(delete ):删除当前光标所在行,相当于剪切
删除:dw(delete word):删除当前光标所在位置的单词
删除:d$(delete $) 删除当前光标所在位置至行尾的内容
拼接行:J(join ),删除当前光标所在行行尾的换行符
撤销:u(unsure)
追加数据 :a(add),类似于 “i”
行尾追加 : A(Add)
insert:r char(char表示一个字符):用 char 替换当前光标所在位置的单个字符
insert:R text(相当于insert)直到按下ESC键
复制:v---->移动光标---->y---->p
查找:/+string----->n(next)
替换:s/old/new/
: s/old/new/g :一行命令替换所有 old 。
:n,ms/old/new/g :替换行号 n 和 m 之间所有 old 。
:%s/old/new/g :替换整个文件中的所有 old 。
:%s/old/new/gc :替换整个文件中的所有 old ,但在每次出现时提示。
#!/bin/bash
# This script displays the date and who's logged on
echo -n The time and date are: #注意-n选项不换行
date
echo "Let's see who's logged into the system:" #所有的引号都可以正常输出了
who #可以将 echo 语句添加到shell脚本中任何需要显示额外信息的地方
#!/bin/bash
# display user information from the system.
echo "User info for userid: $USER"
echo UID: $UID #1.环境变量名称之前加上美元符"$"来使用这些环境变量
echo HOME: "$HOME" #2.加上双引号也没有问题
echo "The cost of the item is \$15" #3.想显示"$"符号需要在前面加上反斜杠
# testing variables
days=10 #4.shell脚本会自动决定变量值的数据类型
guest="Katie" #5.变量名区分大小写
echo "$guest checked in $days days ago"
days=5 #6.赋值时不用$,但是引用必须用$符号
guest="Jessica"
echo "$guest checked in $days days ago"
#7.在shell脚本结束时变量会被删除掉
#有两种方法可以将命令输出赋给变量:
#1. 反引号字符( ` ) :注意不是单引号(')
#2. $() 格式
one=`date` #8.shell命令的输出赋给变量方法1
two=$(date) #9.赋值等号和命令替换字符之间没有空格
echo "The date and time are: " $one #
#下面这个例子很常见,它在脚本中通过命令替换获得当前日期并用它来生成唯一文件名。
# copy the /usr/bin directory listing to a log file
today=$(date +%y%m%d) #today存储日期
ls /usr/bin -al > log.$today #ls的输出重定向到log.180515文件中,如果输出文件已经存在了,重定向操作符会用新的文件数据覆盖已有文件(默认的 umask 设置)
在shell脚本中有两种途径来进行数学运算
ARG1 | ARG2
如果 ARG1 既不是null也不是零值,返回 ARG1 ;否则返回 ARG2
ARG1 & ARG2
如果没有参数是null或零值,返回 ARG1 ;否则返回 0
ARG1 < ARG2
如果 ARG1 小于 ARG2 ,返回 1 ;否则返回 0
ARG1 <= ARG2
如果 ARG1 小于或等于 ARG2 ,返回 1 ;否则返回 0
ARG1 = ARG2
如果 ARG1 等于 ARG2 ,返回 1 ;否则返回 0
ARG1 != ARG2
如果 ARG1 不等于 ARG2 ,返回 1 ;否则返回 0
ARG1 >= ARG2
如果 ARG1 大于或等于 ARG2 ,返回 1 ;否则返回 0
ARG1 > ARG2
如果 ARG1 大于 ARG2 ,返回 1 ;否则返回 0
ARG1 + ARG2
返回 ARG1 和 ARG2 的算术运算和
ARG1 - ARG2
返回 ARG1 和 ARG2 的算术运算差
ARG1 * ARG2
返回 ARG1 和 ARG2 的算术乘积
ARG1 / ARG2
返回 ARG1 被 ARG2 除的算术商
ARG1 % ARG2
返回 ARG1 被 ARG2 除的算术余数
STRING : REGEXP
如果 REGEXP 匹配到了 STRING 中的某个模式,返回该模式匹配
match STRING REGEXP
如果 REGEXP 匹配到了 STRING 中的某个模式,返回该模式匹配
substr STRING POS LENGTH
返回起始位置为 POS (从 1 开始计数)、长度为 LENGTH 个字符的子字符串
index STRING CHARS
返回在 STRING 中找到 CHARS 字符串的位置;否则,返回 0
length STRING
返回字符串 STRING 的数值长度
_ + TOKEN :将 TOKEN 解释成字符串,即使是个关键字
(EXPRESSION) : 返回 EXPRESSION 的值
#!/bin/bash
var1=100
var2=45
var3=$(echo "scale=4; $var1 / $var2" | bc)#将 scale 变量设置成了四位小数,并在 expression 部分指定了特定的运算
echo The answer for this is $var3
注意下面的注释:不能加Tab
#!/bin/bash
var1=10.23
var2=43.12
var3=33.2
var4=31
var5=$(bc<
0命令成功结束
1 一般性未知错误
2 不适合的shell命令
126 命令不可执行
127 没找到命令
128 无效的退出参数
128+x 与Linux信号x相关的严重错误
130 通过Ctrl+C终止的命令
255 正常范围之外的退出状态码
#!/bin/bash
#shell中运行的每个命令都使用退出状态码(exit status)告诉shell它已经运行完毕
var1=10
var2=30
var3=$[$var1 + $var2]
exit $var3 #exit 命令的参数中使用变量
#如果值大于255,返回模256后得到的余数
才会
被执行#!/bin/bash
# 这个脚本在 if 行采用了 pwd 命令。如果命令成功结束, echo 语句就会显示该文本字符串
if pwd
then
echo "It worked"
fi
if IamNotaCommand #由于这是个错误的命令,所以它会产生一个非零的退出状态码
then
echo "It "
echo "worked" #这里可以放多条明令
else
echo "It not worked!"
fi
#!/bin/bash
# 甚至可以更进一步,让脚本检查拥有目录的不存在用户以及没有拥有目录的不存在用户。这
# 可以通过在嵌套 elif 中加入一个 else 语句来实现。
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
#
elif ls -d /home/$testuser #每块命令都会根据命令是否会返回退出状态码 0 来执行。记住,bash shell会依次执行 if 语句,
#只有第一个返回退出状态码 0 的语句中的 then 部分会被执行
then
echo "The user $testuser does not exist on this system."
echo "However, $testuser has a directory."
#
else
echo "The user $testuser does not exist on this system."
echo "And, $testuser does not have a directory."
fi
n1 -eq n2
检查 n1 是否与 n2 相等
n1 -ge n2
检查 n1 是否大于或等于 n2
n1 -gt n2
检查 n1 是否大于 n2
n1 -le n2
检查 n1 是否小于或等于 n2
n1 -lt n2
检查 n1 是否小于 n2
n1 -ne n2
检查 n1 是否不等于 n2
#!/bin/bash
# Using numeric test evaluations
#使用中括号进行数值测试
value1=10
value2=11
#
if [ $value1 -gt 5 ] #但是只能测试整数
then
echo "The test value $value1 is greater than 5"
fi
#
if [ $value1 -eq $value2 ]
then
echo "The values are equal"
else
echo "The values are different"
fi
str1 = str2
检查 str1 是否和 str2 相同
str1 != str2
检查 str1 是否和 str2 不同
str1 < str2
检查 str1 是否比 str2 小
str1 > str2
检查 str1 是否比 str2 大
-n str1
检查 str1 的长度是否非0
-z str1
检查 str1 的长度是否为0
在比较测试中,大写字母被认为是小于小写字母的。但 sort 命令恰好相反,因为sort使用的是系统的本地化语言设置中定义的排序顺序,而比较测试中使用的是标准的ASCII顺序
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 \> $val2 ] #注意,必须加斜杠,否则会被当成重定向符
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi
# testing string length
val1=testing
val2=''
#
if [ -n $val1 ]
then
echo "The string '$val1' is not empty"
else
echo "The string '$val1' is empty"
fi
#
if [ -z $val2 ]
then
echo "The string '$val2' is empty"
else
echo "The string '$val2' is not empty"
fi
#
if [ -z $val3 ]
then
echo "The string '$val3' is empty"
else
echo "The string '$val3' is not empty"
fi
检查 file 是否存在并是一个目录 | -d file |
---|---|
检查 file 是否存在 | -e file |
检查 file 是否存在并是一个文件 | -f file |
检查 file 是否存在并可读 | -r file |
检查 file 是否存在并非空 | -s file |
检查 file 是否存在并可写 | -w file |
检查 file 是否存在并可执行 | -x file |
检查 file 是否存在并属当前用户所有 | -O file |
检查 file 是否存在并且默认组与当前用户相同 | -G file |
检查 file1 是否比 file2 新 ,必须先确认文件是存在的 | file1 -nt file2 |
检查 file1 是否比 file2 旧 | file1 -ot file2 |
#!/bin/bash
# Look before you leap
# 文件测试
jump_directory=/home/hzq
#
if [ -d $jump_directory ]
then
echo "The $jump_directory directory exists"
cd $jump_directory
ls
else
echo "The $jump_directory directory does not exist"
fi
if-then 语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:
#!/bin/bash
# using double parenthesis
#
val1=10
#
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
# val++ 后增
# val-- 后减
# ++val 先增
# --val 先减
# ! 逻辑求反
# ~ 位求反
# ** 幂运算
# << 左位移
# >> 右位移
# & 位布尔和
# | 位布尔或
# && 逻辑和
# || 逻辑或
#!/bin/bash
# using pattern matching
# 使用模式匹配
if [[ $USER == r* ]]
then
echo "Hello $USER"
else
echo "Sorry, I do not know you"
fi
#!/bin/bash
# using the case command
# 使用case命令
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica) #")"相当于C语言中的":"
echo "Do not forget to log off when you're done";;
*) #*通配符即匹配所有情况
echo "Sorry, you are not allowed here";;
esac #case语句结束
#!/bin/bash
# another example of how not to use the for command
for test in I don\'t know if "this'll" work #不添加反斜杠会被视作一个字符串
do #如果一个词语中有空格,需要用双引号圈起来
echo "word:$test"
done
#!/bin/bash
# reading values from a file
file="states"
for state in $(cat $file)
do
echo "Visit beautiful $state"
done
for语句中的list中,环境变量 IFS(内部字段分隔符)默认会用空格、制表符、换行符作为分隔符
#!/bin/bash
# testing the C-style for loop
for (( i=1; i <= 10; i++ )) #1.变量赋值可以有空格
do #2.条件中的变量不以美元符开头
echo "The next number is $i" #3.迭代过程的算式未用 expr 命令格式
done
##############################
# multiple variables
for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done
##############################
#!/bin/bash
# testing a multicommand while loop
var1=10
while echo $var1 #检查 var1 是否大于等于 0
[ $var1 -ge 0 ] #只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环
do #每次迭代中所有的测试命令都会被执行,区别于C语言的 ||
echo "This is inside the loop"
var1=$[ $var1 - 1 ]
done
#!/bin/bash
# using the until command
var1=100
until echo $var1 #shell会执行指定的多个测试命令,只有在最后一个命令成立时停止
[ $var1 -eq 0 ] #退出状态码不为0,才执行循环中列出的命令
do # -eq :检查是否相等
echo Inside the loop: $var1
var1=$[ $var1 - 25 ]
done
$ cat test14
#!/bin/bash
# nesting for loops
for (( a = 1; a <= 3; a++ ))
do
echo "Starting loop $a:"
for (( b = 1; b <= 3; b++ ))
do
echo " Inside loop: $b"
done
done
#!/bin/bash
# changing the IFS value
# 通过改变IFS的值处理 /etc/passwd文件
IFS.OLD=$IFS
IFS=$'\n' #先按行处理文件数据
for entry in $(cat /etc/passwd)
do
echo "Values in $entry –"
IFS=: #再把每一行用空格分开
for value in $entry
do
echo " $value"
done
done
#!/bin/bash
# breaking out of an outer loop
for (( a = 1; a < 4; a++ ))
do
echo "Outer loop: $a"
for (( b = 1; b < 100; b++ ))
do
if [ $b -gt 4 ]
then
break 2 #1.注意,加上参数这里可以跳出两层循环
fi
echo " Inner loop: $b"
done
done
#!/bin/bash
# continuing an outer loop
for (( a = 1; a <= 5; a++ ))
do
echo "Iteration $a:"
for (( b = 1; b < 3; b++ ))
do
if [ $a -gt 2 ] && [ $a -lt 4 ]
then
continue 2 #1.加上参数指定要继续执行哪一级循环
fi
var3=$[ $a * $b ]
echo " The result of $a * $b is $var3"
done
done
#!/bin/bash
for file in /home/hzq/*
do
if [ -d "$file" ]
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
#!/bin/bash
# finding files in the PATH
IFS=:
for folder in $PATH #1.遍历每一个PATH目录中的路径
do
echo "$folder:" #2. 打印这些路径
echo "$IFS"
for file in $folder/* #为什么IFS是":",但是这里还是能分开
do
echo "$IFS"
if [ -x $file ]
then
echo " $file"
fi
done
done
#!/bin/bash
# using one command line parameter
#
factorial=1
for (( number = 1; number <= $1 ; number++ ))
do
factorial=$[ $factorial * $number ]
done
echo The factorial of $1 is $factorial
if [ -n "$1" ]&&[ -n "$2" ] #0.注意:这里必须加引号
then
total=$[ $1 * $2 ] #1.一个参数乘以第二个参数
echo The first parameter is $1. #2.参数也可以是字符串,以空格分隔
echo The second parameter is $2. #3.如果参数不止9个,可以用花括号:${10}
echo The total value is $total.
else
echo "please input two number"
fi
echo "$0 is run in the end" #4.$0保存的是脚本的名字
#潜在问题:如果使用另一个命令来运行shell脚本,命令会和脚本名混在一起,出现在 $0 参数中。
echo "$(basename $0)is run in the end " #不过可以这样解决
#!/bin/bash
# testing $* and $@
#
echo
count=1
#
for param in "$*" #$* :所有的参数
do
echo "\$* Parameter #$count = $param"
count=$[ $count + 1 ]
done
#
echo
count=1
#
for param in "$@"
do #$@ :将参数视作单独的单词
echo "\$@ Parameter #$count = $param"
count=$[ $count + 1 ]
done
#!/bin/bash
# demonstrating the shift command
echo
count=1
while [ -n "$1" ]
do
echo "Parameter #$count = $1"
count=$[ $count + 1 ]
shift 2 #向左移动参数,但是$0不变,加上参数表示一次移动两个
done
set -- $(getopt -q ab:cd "$@")
#!/bin/bash
# Extract command line options & values with getopt
#
set -- $(getopt -q ab:cd "$@")
#
echo
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) param="$2"
echo "Found the -b option, with parameter value $param"
shift ;;
-c) echo "Found the -c option" ;;
--) shift
break ;;
*) echo "$1 is not an option";;
esac
shift
done
#
count=1
for param in "$@"
do
echo "Parameter #$count: $param"
count=$[ $count + 1 ]
done
#需要注意的是:getopt 命令并不擅长处理带空格和引号的参数值,如下面这种情况
#$ ./32_getopt.sh -a -b test1 -cd "test2 test3" test4
#!/bin/bash
# Processing options & parameters with getopts
#
echo
while getopts :ab:cd opt #指明要查找哪些命令行选项,以及每次迭代中存储它们的变量名(opt)
do
case "$opt" in
a) echo "Found the -a option" ;; #注意这里没有单破折号,已经移除了
b) echo "Found the -b option, with value $OPTARG" ;;
c) echo "Found the -c option" ;;
d) echo "Found the -d option" ;;
*) echo "Unknown option: $opt" ;;
esac
done
#
shift $[ $OPTIND - 1 ]
#
echo
count=1
for param in "$@"
do
echo "Parameter $count: $param"
count=$[ $count + 1 ]
done
#./32_getopt.sh -b "test1 test2" -a :现在可以正常解析空格了
#./32_getopt.sh -abtest1 :将选项字母和参数值放在一起使用,而不用加空格
#./32_getopt.sh -acde :将命令行上找到的所有未定义的选项统一输出成问号
#!/bin/bash
# testing the read -p option
#
#
echo -n "Enter your name: " # -n 参数使不换行
read name
echo "Hello $name, welcome to my program. "
# -t 指定等待的秒数
read -t 5 -p "Enter your name: " # 不指定变量,数据会放入特殊环境变量REPLY中
echo Hello $REPLY, welcome to my program.
read -p "Please enter your age: " age # -p 命令直接指定提示字符串
days=$[ $age * 365 ]
echo "That makes you over $days days old! "
read -n1 -p "Do you want to continue [Y/N]? " answer
case $answer in # -n 参数指定接收的输入个数
Y | y) echo
echo "fine, continue on…";;
N | n) echo
echo OK, goodbye
exit;;
esac
# -s 参数避免在命令中输入的数据出现在显示器上
read -s -p "Enter your password: " pass #事实是会显示,只是跟背景色一样
echo "Is your password really $pass? "
#!/bin/bash
# reading data from a file
count=1
test="34_read_input.sh"
cat $test | while read line #1.每次读取一行
do #2.
echo "Line $count: $line"
count=$[ $count + 1]
done
echo "Finished processing the file"
shell自动赋予了错误消息更高的优先级
echo "This is an error" >&2
:有意生成一条错误信息exec 1>testout
:用 exec 命令告诉shell在脚本执行期间重定向某个特定文件描述符exec 0< testfile
: exec 命令允许你将 STDIN 重定向到Linux系统上的文件中#!/bin/bash
# using an alternative file descriptor
exec 3>test13out #可以用 exec 命令来给输出分配文件描述符
#exec 3>>test13out #也可以使用 exec 命令来将输出追加到现有文件中
echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
echo "Then this should be back on the monitor"
#!/bin/bash
# storing STDOUT, then coming back to it
exec 3>&1 #1.文件描述符3重定向到标准输出
exec 1>test14out #2.标准输出重定向到文件
echo "This should store in the output file"
echo "along with this line."
exec 1>&3 #3.利用该文件描述符3重定向回 STDOUT
echo "Now things should be back to normal" #+.这句输出到屏幕
#!/bin/bash
# redirecting input file descriptors
exec 6<&0 #1.先用文件描述符 6 用来保存 STDIN 的位置
exec 0< testfile #2.将 STDIN 重定向到一个文件
count=1
while read line #3.read命令的所有输入都来自重定向后的 STDIN
do
echo "Line #$count: $line"
count=$[ $count + 1 ]
done
exec 0<&6 #4.将 STDIN 恢复到原先的位置
read -p "Are you done now? " answer
case $answer in
Y|y) echo "Goodbye";;
N|n) echo "Sorry, this is the end.";;
esac
#!/bin/bash
# testing input/output file descriptor
exec 3<> testfile #1.用exec命令将文件描述符 3 分配给文件 testfile 以进行文件读写
read line <&3 #2.用 read 命令读取文件中的第一行
echo "Read: $line" #3.需要注意:写入文件中的数据会覆盖已有的数据
echo "This is a test line" >&3
#!/bin/bash
# testing closing file descriptors
exec 3> test17file
echo "This is a test line of data" >&3
exec 3>&- #1.要关闭文件描述符,将它重定向到特殊符号 &-
echo "This won't work" >&3 #2.这里shell会生成错误消息
cat test17file #3.打开了同一个输出文件,shell会用一个新文件来替换已有文件
exec 3> test17file
echo "This'll be bad" >&3 #4.所以意味着这几句话会覆盖已有文件
/usr/sbin/lsof -a -p $$ -d 0,1,2
#!/bin/bash
#creating and using a temp file
tempfile=$(mktemp test19.XXXXXX) #生产一个临时文件
exec 3>$tempfile #输出重定向到该文件
echo "This script writes to temp file $tempfile"
echo "This is the first line" >&3
echo "This is the second line." >&3
echo "This is the last line." >&3
exec 3>&- #关闭文件描述符
echo "Done creating temp file. The contents are:"
cat $tempfile
rm -i $tempfile 2> /dev/null #删除文件,并把删除的提示信息输出到/dev/null,即不显示
#!/bin/bash
# using a temporary directory
tempdir=$(mktemp -d dir.XXXXXX) #创建临时文件夹
cd $tempdir
tempfile1=$(mktemp temp.XXXXXX)
tempfile2=$(mktemp temp.XXXXXX)
exec 7> $tempfile1 #重定向文件描述符到文件
exec 8> $tempfile2
echo "Sending data to directory $tempdir"
echo "This is a test line of data for $tempfile1" >&7
echo "This is a test line of data for $tempfile2" >&8
#!/bin/bash
# Modifying a set trap
#
trap "echo ' Sorry... Ctrl-C is trapped.'" SIGINT
#捕获"终止进程"信号
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count + 1 ]
done
#
trap "echo ' I modified the trap!'" SIGINT
#到这里处理信号的方式已经变了
count=1
while [ $count -le 5 ]
do
echo "Second Loop #$count"
sleep 1
count=$[ $count + 1 ]
done
trap -- SIGINT #删除设置好的捕获,单破折号也能起作用
echo "Ctrl-C can use le"
count=1
while [ $count -le 5 ]
echo "Second Loop #$count"
sleep 1
count=$[ $count + 1 ]
done
./test4.sh &
:只需要像这样,在命令后面加一个&,但是这样还是会有输出,不要奇怪nohup ./test1.sh &
:可以用nohup命令,阻断所有发送给该进程的SIGHUP信号,输出会被保存到nohup.out文件中jobs -l
bg
:以后台模式重启一个作业,如果有多个就得加作业号fg 2
:以前台模式重启作业,可用带有作业号的 fg 命令从-20(最高优先级)到+19(最低优先级),默认以0优先级启动,可以记做"好人难做"
nice -n 10 ./test4.sh > test4.out &
:nice命令指定运行的优先级
renice -n 10 -p 5055
at [-f filename] time
:指定Linux系统何时运行脚本
atq
:查看系统中有哪些作业在等待atrm 18
:根据作业号删除指定作业date +%d -d tomorrow
= 01 ] ; then ; command :每个月的最后一天执行的命令period delay identifier command
function divem { echo $[ $1 / $2 ]; }
:采用单行方式定义函数
function doubleit { read -p "Enter value: " value; echo $[$value * 2 ]; }
:需要注意的是得加分号,这样才知道起止位置
$ function multem {
echo $[ $1 * $2 ]
}
. /home/rich/libraries/myfuncs
:可以在bashrc文件末尾加上你自己的函数库
sed options script file
echo "This is a test" | sed 's/test/big test/'
sed 's/dog/cat/' data1.txt
:不过不会修改文本文件的数据,只是显示到STDOUTsed -e 's/brown/green/; s/dog/cat/' data1.txt
:使用多个命令需要用-e参数sed -e '
:然后把命令一条一条输进去sed -f script1.sed data1.txt
:也可以把上述三条命令放进一个文件,通过-f参数指定这个文件,去处理data1.txtgawk options program file
gawk '{print "Hello World!"}'
:对每行文本执行脚本gawk '{print $1}' data2.txt
:打印date2.txt文件中每行的第一个单词,默认是空白字符或者制表符作为分隔符gawk -F: '{print $1}' /etc/passwd
:-F指定字段分隔符echo "My name is Rich" | gawk '{$4="Christine"; print $0}'
:要执行多个命令,只需要用";"分隔gawk '{
:也可以用此提示符一行一行的输入gawk -F: -f script2.gawk /etc/passwd
:可以把命令放到script.gawk文件中,通过-f参数运行sed '2,$s/test/trial/' data4.txt 3gpw data4s.txt
:转义字符前加""
sed '/Samantha/s/bash/csh/' /etc/passwd
:Samantha这里可以替换成正则表达式,所以整句只查找正则表达式匹配到的行sed '3d' data6.txt
:删除第三行sed '2,3d' data6.txt
:删除2~3行sed '3,$d' data6.txt
:删除第三行开始以后的所有行sed '/number 1/d' data6.txt
:删除出现number 1的行sed '/1/,/3/d' data6.txt
:第一个模式打开删除功能,第二个模式关闭删除功能,sed编辑器会删除两个指定行之间的所有内容,如果后面又匹配到1,又会打开删除模式echo "Test Line 2" | sed 'i\Test Line 1'
:-i参数在指定行前面插入一行echo "Test Line 2" | sed 'a\Test Line 1'
:-a参数在指定行后面添加一行sed '3i\> This is an inserted line.' data6.txt
:这是一个将新行插入到第三行前面的例子sed '$a\> This is a new line of text.' data6.txt
附加到末尾sed '3c\ This is a changed line of text.' data6.txt
:-c参数指定修改模式,这里修改第三行sed '/number 3/c\ This is a changed line of text.' data6.txt
:也可以通过模式匹配的方式修改sed '2,3c\ This is a new line of text.' data6.txt
:也可以使用区间地址,但是这一行会覆盖2、3两行sed 'y/123/789/' data8.txt
:1替换成9,2替换成8,3替换成9,直到替换完所有的字符sed -n '/number 3/p' data6.txt
:-p参数表打印模式,-n参数用来禁止输出其他行sed '=' data1.txt
:"="打印的会输出行号sed -n 'l' data9.txt
:打印数据流中的文本和不可打印的ASCII字符sed '1,2w test.txt' data6.txt
:将数据流中的前两行打印到文件中sed '3r data12.txt' data6.txt
:将data12.txt中的数据插入到data6.txt的第三行后面sed '/number 2/r data12.txt' data6.txt
:将data12中的数据插入到匹配行的后面sed '$r data12.txt' data6.txt
:插入到末尾echo "This is a test 1" | sed -n '/test 1/p'
:p命令输出匹配到的行,注意空格和其他字符并没有什么区别echo "This is a test" | gawk '/tes/{print $0}'
:print命令输出匹配到的行,注意两种写法都区分大小写,不用写出完整单词.*[]^${}\+?|()
sed -n '/\$/p' data2
:使用特殊字符必须转义echo "3 / 2" | sed -n '/\//p'
:注意,使用正斜线也必须转义echo "Books are great" | sed -n '/^ Book/p'
:Book必须出现在行首才能匹配到echo "This ^ is a test" | sed -n '/s ^ /p'
:脱字符放在其他地方就变成普通字符了echo "This is a good book" | sed -n '/book$/p'
:字符"$"指明数据行必须以该文本结尾sed -n '/^ this is a test$/p' data4
:会忽略那些不单单只包含这些文本的行sed '/^ $/d' data5
:删除文本中的空白行sed -n '/.at/p' data6
:"."匹配任意一个字符,如果没有(如行首)则匹配失败sed -n '/[ch]at/p' data6
:[ch]字符组取代"."使通配符精确一点,不过必须有一个字符组中的字符被匹配到sed -n ' /^ [0123456789][0123456789]$/p ' data8
:匹配只出现两个数字的一行sed -n '/[^ ch]at/p' data6
:在字符组的开头加上脱字符,就成了了排除型字符组sed -n '/^[0-9][c-h][a-ch-m]$/p' data8
:单破折号表示linux字符集中得字符,即这样可以表示区间,最后一个区间表示ac,hmecho "ieeeek" | sed -n '/ie*k/p'
:字符后面放*,表示该字符要出现一次或多次echo "this is a regular pattern expression" | sed -n '/regular.*expression/p'
:__.*
__的组合表示若干字符echo "bt" | gawk '/b[ae]?t/{print $0}'
:?表示字符组出现了一次或零次,另外,注意sed不支持扩展的正则表达式echo "beeet" | gawk '/be+t/{print $0}'
:加号表示+前面的字符至少出现一次echo "bet" | gawk --re-interval '/be{1}t/{print $0}'
:{}中的1表示e刚好出现了一次echo "bt" | gawk --re-interval '/be{1,2}t/{print $0}'
:{}中的1,2表示至少出现一次,最多出现两次echo "The cat is asleep" | gawk '/cat|dog/{print $0}'
:管道允许匹配两个模式中的任何一个echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
:()能对字符进行分组,即表示urday是一个整体