1.初始Linux shell
Linux内核
系统内存管理 软件程序管理 硬件设备管理:字符型、块、网络设备文件 文件系统管理 GNU工具:coreutils软件包 图形化桌面环境:X Window、KDE、GNOME、Unity 应用软件
2.走进shell
设置终端颜色
setterm -foreground blue setterm -background yellow 清除设置并清屏:setterm -reset 控制台终端:退出图形化桌面模式,进入文本模式 图形化终端:图形化界面里的Terminal
3.基本的bash shell命令
man 链接:
符号链接:ln -s 源文件 链接文件 (链接文件为新文件) 硬链接:ln 源文件 链接文件(链接文件和源文件指向同一个文件) mv 移动文件或重命名文件,文件的inode不变 。 ls -i tree file 文件类型
4.更多的bash shell命令
ps top kill killall mount umount df du sort -t ‘:’ -k 3 -n /etc/passwd grep egrep fgrep 压缩数据:gzip gzcat gunzip 归档数据:tar
创建归档文件:tar -cvf test.tar test1/ test2/ 查看归档文件:tar -tf test.tar 提取归档文件:tar -xvf test.tar
5.理解shell
进程列表:括号使命令列表变成了进程列表,生成一个子shell来执行对应的命令
[ root@localhost ~]
/root
anaconda-ks.cfg
/etc
/root
anaconda-ks.cfg
PID TTY TIME CMD
1833 pts/0 00:00:00 bash
1990 pts/0 00:00:00 \ _ ps
0
[ root@localhost ~]
/root
anaconda-ks.cfg
/etc
/root
anaconda-ks.cfg
PID TTY TIME CMD
1833 pts/0 00:00:00 bash
1991 pts/0 00:00:00 \ _ bash
1994 pts/0 00:00:00 \ _ ps
1
[ root@localhost ~]
/root
1
[ root@localhost ~]
/root
2
将进程置入后台
‘&’ 查看后台进程:jobs -l 协程:
coproc sleep 10 coproc My_Job {sleep 10} 内建命令和外部命令的区别在于前者不需要使用子进程来执行。它们已经和shell编译成一体,作为shell工具的组成部分存在。
[ root@localhost ~]
ps is hashed ( /usr/bin/ps)
[ root@localhost ~]
cd is a shell builtin
[ root@localhost ~]
pwd is a shell builtin
pwd is /usr/bin/pwd
history
a 强制写入history文件(.bash_history) n 同步,当存在多个客户端时 c 清除 !! 执行上一条命令;!20 执行第20条命令 alias 别名
p 查看当前可用别名 创建别名 alias lxq=‘ls -la’
6.什么是环境变量
全局环境变量对于shell绘画和所有生成的子shell都是可见的。局部变量则值对创建它们的shell可见。 printenv和env 显示全局变量,set显示全局变量、局部变量和用户自定义变量 设置用户自定义变量,变量名、等号和值之间不能有空格。my_variable=“Hello World” 设置全局变量:先创建局部环境变量,然后再把它导出到全局环境中。export my_variable
修改子shell中全局变量并不会影响到父shell中该变量的值。 删除环境变量:unset my_variable
在子shell中删除全局变量,并不会影响父shell全局变量 常用的环境变量
UID、EUID PPID:父进程ID RANDOM:0~32767的随机数 BASH_ARGC、BASH_ARGV FUNCNAME:当前执行的函数名称 HOSTNAME 设置环境变量:PATH,定义了用于执行命令和程序查找的目录。PATH=$PATH:/home/work/bin 启动bash shell的三种方式
登录时作为默认登录shell。会从5个不同的启动文件里读取命令
/etc/profile。此脚本会加载/etc/profile.d文件夹下的脚本 用户专属启动文件,shell会按如下顺序查找如下三个文件,找到第一个余下的被忽略
$HOME/.bash_profile $HOME/.bash_login $HOME/.profile $HOME/.bashrc 作为非登录shell的交互式shell:(例如在命令行下敲入 bash),它不会访问/etc/profile,只会检查用户HOME目录中的.bashrc文件 作为运行脚本的非交互shell:系统执行shell脚本。当shell启动一个非交互shell时,它会检查BAHS_ENV环境变量查看执行的启动文件,如果没有BASH_ENV,那么作为子shell的,子shell继承父shell的导出的变量,不启动子shell的,局部变量和全局变量已存在与当前shell中 环境变量持久化:
对于全局变量,可在/etc/profile中添加,但是此文件会随着发行版升级版本变化,最好是在/etc/profile.d目录中创建一个.sh结尾的文件。把所有新的和修改过的全局变量设置在这个文件中 存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件 数组变量:要给某个环境变量设置多个值,可以把值放在括号里,用空格分割。数组变量可移植性不好,在其他shell中可能存在问题,慎重使用
mytest = ( one two three four five)
echo $mytest
echo ${mytest[ 1] }
echo ${mytest[ *] }
mytest[ 2 ] = lxq
unset mytest[ 2 ]
7.Linux的安全性
useradd work [-G groupname] userdel -r work # r删除work的HOME目录以及邮件目录 usermod:修改用户账户
L锁定账户,无法登录 U解锁账户 G 添加组:usermod -G groupname username passwd、chpasswd 批量修改用户名密码 chsh:修改默认用户登录sh,chsh -s /bin/csh test chfn:修改账户备注信息,grep work /etc/passwd可查看修改结果 chage用来帮助管理用户账户有效期 groupadd [groupname] groupmod -n working work # 修改组名 umask:默认文件权限。对于文件,全权限值为666,对于目录全权限值为777
touch test.txt
mkdir test.d
drwxr-xr-x. 2 root root 6 Jan 23 19 :29 test.d
-rw-r--r--. 1 root root 0 Jan 23 19 :29 test.txt
chmod:权限修改。 R 递归作用 chown:属主修改。 R 递归作用
修改用户:chmod work test.txt 修改用户和组:chmod work.work test.txt 修改用户和组:chmod work. test.txt 修改组:chmod .work test.txt chgrp:修改数组 共享文件。SGID位对于文件共享非常重要。启用SGID位后,可以强制在一个共享目录下创建新文件都属于该目录的属组,这个组就成为了每个用户的属组。
SUID(4):当文件被用户使用时,程序会以未见属主的权限运行。chmod u+s file SGID(2):对文件来说,程序会以文件数组的权限运行;对于目录来说,目录中创建的新文件会以目录的默认属组作为默认属组。chmod g+s file 粘着位(1):进程结束后文件还驻留(粘着)在内存中。chmod o+t file
8.管理文件系统
日志文件系统:ext4、XFS 写时复制文件系统:ZFS、Btrf,如果修改数据,会使用克隆或可写快照 创建分区 fdisk
fdisk -l 列出分区信息 fdisk /dev/sdb 操作分区 挂载 mount -t ext4 /dev/sdb1 /mnt/my_partition 文件系统检查:fsck
逻辑卷管理
物理卷(physical volume,PV):每个物理卷都会映射到硬盘上特定的物理分区 卷组(volume group,VG):多个物理卷集中在一起可以形成一个卷组。逻辑卷管理系统将卷组视为一个物理硬盘,但事实上卷组可能是由分区在多个物理硬盘上的多个物理分区组成的。卷组提供了一个创建逻辑分区的平台,而这些逻辑分区则包含了文件系统。 逻辑卷(logical volume,LV):为Linux提供创建文件系统的分区环境 快照snapshot: 镜像:实时更新的逻辑卷的完整副本,当创建镜像逻辑卷时,LVM会将原始逻辑卷同步到镜像副本中 条带化:跨多个硬盘创建逻辑卷,文件数据块分散到多个硬盘,增加性能 使用LVM
fdisk -l
fdisk /dev/sdc
Command ( m for help ) : n
Partition type
p primary ( 0 primary, 0 extended, 4 free )
e extended ( container for logical partitions)
Select ( default p) :
Using default response p.
Partition number ( 1 -4, default 1 ) :
First sector ( 2048 -16777215, default 2048 ) :
Last sector, +sectors or +size{ K,M,G,T,P} ( 2048 -16777215, default 16777215 ) : +2G
Created a new partition 1 of type 'Linux' and of size 2 GiB.
Command ( m for help ) : t
Selected partition 1
Hex code ( type L to list all codes) : 8e
Changed type of partition 'Linux' to 'Linux LVM' .
Command ( m for help ) : p
Disk /dev/sdc: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size ( logical/physical) : 512 bytes / 512 bytes
I/O size ( minimum/optimal) : 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe54e9c4c
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 4196351 4194304 2G 8e Linux LVM
Command ( m for help ) : w
The partition table has been altered.
Calling ioctl( ) to re-read partition table.
Syncing disks.
pvcreate /dev/sdc1 /dev/sdc2 /dev/sdc3 /dev/sdb1 /dev/sdb2 /dev/sdb3
pvdisplay
vgcreate vg_lxq /dev/sdc1 /dev/sdc3 /dev/sdb1 /dev/sdb3
vgdisplay vg_lxq
lvcreate -L 3G -n lv_sda1 vg_lxq
lvdisplay vg_lxq
mkfs.ext4 /dev/vg_lxq/lv_sda1
mount /dev/vg_lxq/lv_sda1 /mnt/my_partition
mount
lvresize -L 4G /dev/vg_lxq/lv_sda1
e2fsck -f /dev/vg_lxq/lv_sda1
resize2fs /dev/vg_lxq/lv_sda1
umount /dev/vg_lxq/lv_sda1
e2fsck -f /dev/vg_lxq/lv_sda1
resize2fs /dev/vg_lxq/lv_sda1 3G
lvresize -L 3G /dev/vg_lxq/lv_sda1
lvcreate -L 1G -n lv_sda2 vg_lxq
mkfs.xfs /dev/vg_lxq/lv_sda2
mkdir /mnt/my_xfs
mount /dev/vg_lxq/lv_sda2 /mnt/my_xfs
lvresize -L 2G /dev/vg_lxq/lv_sda2
xfs_growfs /dev/vg_lxq/lv_sda2
umount /dev/vg_lxq/lv_sda2
dd if = /dev/zero bs = 1M count = 1000 of = /mnt/my_xfs/test1000M.zero
vgreduce vg_lxq /dev/sdc1
vgextend vg_lxq /dev/sdc2
lvcreate -s -L 500M -n lvsda1snap2 /dev/vg_lxq/lv_sda1
lvdisplay /dev/vg_lxq/lvsda1snap2
9.安装软件程序
yum list
yum list nginx
yum list installed
yum list installed nginx
yum provides /etc/yum.conf
yum install nginx
yum localinstall package_name.rpm
yum list updates
yum update package_name
yum update
yum remove package_name
yum erase package_name
yum clean all
yum deplist package_name
11.构建基本脚本
echo -n 无换行符 命令替换
管道(|),不要以为管道串起的两个命令会依次执行。Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来,在第一个命令产生输出的同时,输出会立即送往第二个命令。数据传输不会用到任何中间文件或缓冲区。执行数学运算,bash shell 只支持整数运算,浮点运算可考虑使用zsh、bc计算器
var1 = $( expr 2 \ * 5 )
var2 = $[ 2 *5]
var1 = $( echo "3+4" | bc )
var5 = $( bc << EOF
scale=4
a1 = ($var1 * $var2 )
a2 = ($var3 * $var4 )
a1+a2
EOF )
12.使用结构化命令
if-then:if后面的命令的退出状态码为0(该命令成功执行),位于then部分的命令就会被执行。
if pwd
then
echo "It worked"
else
echo "It don't worked"
fi
if pwd ; then
xxx
elif ls -d /home/work ; then
xxx
else
xxx
fi
test:提供了在if-then语句中测试不同条件的路径。如果test命令列出的条件成立,test命令就会退出并返回退出状态码0;不成立则返回非零退出状态码。test可处理下列三种条件
数值比较,-eq -ge -gt -le -lt -ne 字符串比较,= != < >
< > 必须采用转义 -n str1 检查str1的长度是否为非0 -z str1 检查str1的长度是否为0 文件比较
-d file 检查file是否存在并且是一个目录 -f file 检查file是否存在并且是一个文件 -e file 检查file是否存在 -[r|w|x] file 检查file是否可读、可写、可执行 -s file 检查file是否存在并非空 -O file 检查file是否存在并属于当前用户所有 -G file 检查file是否存在并且默认组与当前用户相同 file1 -nt file2 检查file1是否比file2新 file1 -ot file2 检查file1是否比file2旧 test命令可用中括号代替,在第一个方括号之后和第二个方括号之前必须加上一个空格,否则会报错。if [ condition ];then fi 复合条件测试 [ cond1 ] && [ cond2 ];[ cond1 ] || [ cond2 ]; 使用双括号命令允许正在比较过程中使用高级数学表达式
if (( 3 ** 4 == 81 )) ; then
echo "3**4==81"
fi
if [ [ $USER == r* ] ] ; then
echo "user r*"
fi
case语句,|可以匹配多个值,;;为每一个case结束,*)捕获所有和已知模式不匹配的值。
case $USER in
rich | junmo)
echo "xxx"
echo "hello" ; ;
testing)
echo "testing" ; ;
*)
echo "default" ; ;
esac
13.更多的结构化命令
内部字段分隔符IFS,bash shell默认把空格、制表符、换行符当做字段分隔符。
IFS = :
IFS = $'\n ' : ; "
IFS .OLD= $IFS
IFS = $'\n '
IFS = $IFS .OLD
for test in I don\ 't know if "this'll" work
do
echo $test
done
list = "AB C D E"
list = $list " F"
for state in $list
do
echo $state
done
for f in $( cat $file)
do
echo $f
done
for file in /etc/* /home/work
do
if [ -d "$file " ]
then
echo "$file is a directory"
elif [ -f "$file " ]
then
echo "$file is a file"
fi
done
for (( i = 0 ; i< 10 ; i++ ))
do
echo "index $i "
done
while:使用多个测试命令时,每个测试命令为一行,只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环
var1 = 10
while echo $var1
[ $var1 -ge 0 ]
do
echo "This is inside the loop"
var1 = $[ $var1 - 1 ]
done
until命令:和while相反,当命令执行退出状态码返回零时退出 嵌套循环nested loop 循环处理文件数据
IFS .OLD= $IFS
IFS = $'\n '
for entry in $( cat /etc/passwd)
do
echo "Value in $entry -"
IFS = :
for value in $entry
do
echo " $value "
done
done
IFS = $IFS .OLD
控制语句break continue,其中break n为打断第n层外部循环 循环输出,可以在done之后重定向到文件,也可以使用管道符,如 done>test123.txt; done | sort
14.处理用户输入
命令行参数
1
,
1,
1 , {10} 读取脚本名
0
,
0,
0 , (basename $0) [ -n “$1” ] 测试参数是否存在 参数个数: $# 最后一个变量: ${!#} 抓取所有数据,$* 和
@
,
@ ,
@ , * 变量会将所有参数当成单个参数,而 $@ 变量会单独处理每个参数 shift移动变量,可以用来跳过不需要的变量
echo "first parm: $1 "
shift 2
echo "first parm: $1 "
处理选项getopt:将命令行选项和参数处理只生成一个输出。命令行执行:
$ getopt ab:cd -a -btest1 -cd test1 test2
-a -b test1 -c -d -- test1 test2
处理选项getopts:shell内置命令,每次调用只检测一个参数,$OPTARG为当前解析的值,OPTIND为当前处理的位置加1
while getopts :ab:c 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" ; ;
*) echo "Unknown option: $opt "
esac
done
shift $[ $OPTIND -1 ]
count = 1
for param in "$@ "
do
echo "Parameter $count : $param "
count = $[ $count + 1 ]
done
$ bash a.sh -a -btest1 -c -- testaaa sjsjjs
Found the -a option
Found the -b option, with value test1
Found the -c option
Parameter 1 : testaaa
Parameter 2 : sjsjjs
获取用户输入:read,如果没有指定变量,则在全局变量REPLY中
read -p "Enter your name: " name
read name
read -t 5 name
read -n 1 name
read -s pass
count = 1
cat test.txt | while read line
do
echo "Line $count : $line "
count = $[ $count +1 ]
done
15.呈现数据
STDIN 0 ;STDOUT 1 ;STDERR 2; 重定向错误 2> 重定向错误和数据 &> 临时重定向:在重定向到文件描述符时,必须在文件描述符数字之前加一个 &
echo "this is an error" > &2
永久重定向:在脚本中使用exec告诉脚本执行期间重定向某个特定文件描述符
exec 1 > testout
exec 2 > testerror
#!/bin/bash
exec 0 < a.sh
count = 1
while read line
do
echo "Line #$count : $line "
count = $[ $count +1 ]
done
exec 3 > test13out
echo "test13out hhh" > &3
exec 3 >&1
exec 1 > testout
exec 1 >&3
创建读写文件描述符 exec 3<> testfile 关闭文件描述符 exec 3>&- 列出打开的文件描述符:lsof 组织命令输出 2> /dev/null 创建临时文件 mktemp
mktemp testing.XXXXX
mktemp -t testing.XXXXX
mktemp -d dir.XXXXX
tee file:将STDIN的数据发往STDOUT和文件file,追加数据到文件使用 -a 选项
16.控制脚本
SIGINT:CTRL+C会生成此信号 SIGTSTP:Ctrl+Z 捕获信号:trap commands signals
捕获信号:trap “echo ’ Sorry… Ctrl+C is trapped.’” SIGINT 捕获脚本退出:trap “echo Goodbye…” EXIT 修改捕获:trap “echo ’ I modified the trapped.’” SIGINT 移除捕获:trap – SIGINT
#!/bin/bash
trap "echo Goodbye..." EXIT
trap "echo ' Sorry... Ctrl+C is trapped.'" SIGINT
count = 1
while [ $count -le 5 ] ; do
echo "Loop1: #$count "
sleep 1
count = $[ $count +1 ]
done
trap "echo ' I modified the trapped.'" SIGINT
count = 1
while [ $count -le 5 ] ; do
echo "Loop2: #$count "
sleep 1
count = $[ $count +1 ]
done
trap -- SIGINT
count = 1
while [ $count -le 5 ] ; do
echo "Loop2: #$count "
sleep 1
count = $[ $count +1 ]
done
后台运行脚本:&,但是要注意在终端会话退出时,后台进程也会随之退出,因为终端退出时,会给它的子进程发送SIGHUB信号 nohup命令会解除终端和进程的关联 作业控制jobs
l 列出进程PID及作业号 n 只列出上次shell发出通知后改变状态的作业 p 只列出PID r 只列出运行中的作业 s 只列出已停止的作业 重启停止作业
调整谦让度
nice -n 10 ./test.sh & renice -n 15 -p 22233 定时任务
一次性执行 at 周期性执行 cron ancron:处理由于关机错过的脚本任务
17.创建函数
函数 function name {} 返回值:
使用return返回状态码,范围为0~255,必须函数结束就获取 使用函数输出
function foo {
read -p "Enter a value: " value
echo "doubling the value"
return $[ $value * 2 ]
}
foo
echo "The new value is $? "
function bar {
read -p "Enter a value: " value
echo $[ $value * 2 ]
}
result = $( bar)
echo "The new value is $result "
函数传递参数 foo param1 param2 …,获取参数为 $1 $2 …, 全局变量:默认情况下,在脚本中定义的任何变量都是全局变量,在函数内可正常访问
#!/bin/bash
function ttt {
aaa = $[ $aaa *2 ]
}
aaa = 10
ttt
echo "aaa: $aaa "
$( ttt)
echo "aaa: $aaa "
function ttt {
local aaa = $[ $aaa *2 ]
}
aaa = 10
ttt
echo "aaa: $aaa "
#!/bin/bash
function ttt {
local aaa = ( $( echo "$@ " ) )
echo "new array: ${aaa[ *] } count:$# "
}
function ttt2 {
local aaa = ( $( echo "$@ " ) )
local reaaa
for (( i= 0 ; i< $#; i++ ))
{
reaaa[ $i ] = $[ ${aaa[ $i] } * 2 ]
}
echo ${reaaa[ *] }
}
aaa = ( 10 20 30 40 50 )
echo "original arr: ${aaa[ *] } "
ttt ${aaa[ *] }
arg = $( ttt2 ${ aaa[ *] } )
echo $arg
arg = ( $( ttt2 ${ aaa[ *] } ) )
echo $arg
echo ${arg[ *] }
function factorial {
if [ $1 -eq 1 ]
then
echo 1
else
local temp = $[ $1 - 1 ]
local result = $( factorial $temp)
echo $[ $result * $1 ]
fi
}
创建库,使用库函数的关键在于source命令。source会在当前shell上下文中执行命令,而不是新建一个shell。可以用source在shell脚本中运行库文件脚本,source有个快捷命名,称为点操作符
#!/bin/bash
. ./my_func.sh
命令行使用函数
可在命令行直接创建函数 在.bashrc里创建函数,也可以在.bashrc里引入函数库
18.图形化桌面环境的脚本编程
#!/bin/bash
function diskspace {
clear
df -k
}
function whoseon {
clear
who
}
function memusage {
clear
cat /proc/meminfo
}
function memu {
clear
echo
echo -e "\t \t \t Sys Admin Memu\n "
echo -e "\t 1. Display disk space"
echo -e "\t 2. Display logged on users"
echo -e "\t 3. Display memory usage"
echo -e "\t 0. Exit program\n \n "
echo -en "\t \t Enter option: "
read -n 1 option
}
PS3 = "Enter option: "
select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"
do
case $option in
"Exit program" ) break ; ;
"Display disk space" ) diskspace ; ;
"Display logged on users" ) whoseon ; ;
"Display memory usage" ) memusage ; ;
*)
clear
echo "Sorry, wrong selection" ; ;
esac
echo -en "\n \n \t \t Hit any key to continue."
read -n1 line
done
dialog:每个dialog提供两种输出,可以通过退出状态码来确定用户选择了那个按钮,如果选择了Yes或OK按钮,返回状态码为0;如果选择了Cancel或No按钮则退出状态码为1。如果部件返回了数据,那么命令会将数据发送到STDERR
msgbox:对话框显示一条消息,直到用户点击ok才消失。dialog --msgbox text height width
dialog --title “lxq” --msgbox “this is a msg” 10 20 yesno部件:扩展了msgbox部件,有两个按钮
dialog --title “lxq” --yesno “this is a msg” 10 20 inputbox:提供了一个简单的文本框区域来输入文本字符串
dialog --title “inputbox lxq” --inputbox “Enter your age” 10 20 2>age.txt textbox:在窗口中显示大量信息的方法,如下展示/etc/passwd文件的内容
dialog --textbox /etc/passwd 10 20 menu部件:dialog --menu title height width 每页数量
dialog --menu “Sys Admin Menu” 20 30 10 1 “Display disk space” 2 “Display logged on users” 3 “Display memory usage” 4 “Exit program” 2> test.txt fselect: 处理文件夹
dialog --title “Select a file” --fselect $HOME/ 10 20 2>file.txt 图形化X Window环境下
KDE桌面:kdialog GNOME桌面:gdialog和zenity