shell在linux里摇摇晃晃
1.shell不只是一種解釋器,還是一種編程工具
查看系統(tǒng)中可用的shell,linux默認(rèn)使用 Bash Shell
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
redhat系將/bin/sh連接到bash上
[root@localhost ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 May 17 08:32 /bin/sh -> bash
[root@localhost ~]# bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
2.shell的功能
當(dāng)一臺(tái)系統(tǒng)運(yùn)行起來時(shí),內(nèi)核會(huì)被調(diào)入內(nèi)存中運(yùn)行,由內(nèi)核執(zhí)行所有底層的工作,它會(huì)將所有應(yīng)用程序及用戶的數(shù)據(jù)翻譯為CPU的基本指令,并將其送至處理器。為了對(duì)用戶屏蔽這些復(fù)雜的技術(shù)細(xì)節(jié),同時(shí)也是為了保護(hù)內(nèi)核不會(huì)因?yàn)橛脩糁苯硬僮鞫艿綋p害,有必要在內(nèi)核之上創(chuàng)建一個(gè)層,該層就是一個(gè)"殼",也就是shell。
工作模式:互動(dòng)模式和腳本模式
3.運(yùn)行腳本
第一種:直接在該腳本所在目錄中直接bash該腳本,腳本中的#!/bin/bash可以省略
第二種:給該腳本加上可執(zhí)行權(quán)限,然后使用"./腳本名"來運(yùn)行,沒有權(quán)限會(huì)報(bào)錯(cuò)
第三種:把腳本的移動(dòng)到$PATH的任意路徑下,,使其成為默認(rèn)的系統(tǒng)命令
4.腳本排錯(cuò)
加入echo或者echo結(jié)合sleep
借助-x參數(shù)來觀察腳本的運(yùn)行情況:bash -x helloworld.sh
為了更精細(xì)地調(diào)試運(yùn)行shell,我們可以借助第三方工具bashdb。這是一個(gè)類似于GDB的腳本調(diào)試軟件,小巧而強(qiáng)大,具有設(shè)置斷點(diǎn)、單步執(zhí)行、觀察變量等功能。
5.shell的內(nèi)建命令
就是bash自身提供的命令,而不是文件系統(tǒng)中的某個(gè)可執(zhí)行文件。比如人類的語言溝通就是與生俱來的能力,而移動(dòng)電話只是一個(gè)用來溝通的外部工具。
通常來說,內(nèi)建命令會(huì)比外部命令執(zhí)行得更快,執(zhí)行外部命令時(shí)不但會(huì)觸發(fā)磁盤I/O,還需要fork出一個(gè)單獨(dú)的進(jìn)程來執(zhí)行,執(zhí)行完后再退出。而執(zhí)行內(nèi)建命令相當(dāng)于調(diào)用當(dāng)前shell進(jìn)程的一個(gè)函數(shù)。
判斷一個(gè)命令是否為外部命令
cd是一個(gè)內(nèi)建命令
[root@localhost ~]# type cd
cd is a shell builtin
ifconfig是一個(gè)外部命令
[root@localhost ~]# type ifconfig
ifconfig is /usr/sbin/ifconfig
6.執(zhí)行程序
"."(點(diǎn)號(hào))
點(diǎn)號(hào)用于執(zhí)行某個(gè)腳本,甚至腳本沒有可執(zhí)行權(quán)限也可以運(yùn)行,如果你不想修改某個(gè)測(cè)試腳本時(shí),可以這樣用。
[root@localhost ~]# ll helloworld.sh
-rw-r--r-- 1 root root 31 Jul 16 11:04 helloworld.sh
[root@localhost ~]# ./helloworld.sh
bash: ./helloworld.sh: Permission denied
沒有權(quán)限也不會(huì)報(bào)錯(cuò)
[root@localhost ~]# . ./helloworld.sh
hello world
source與點(diǎn)號(hào)類似,source命令也可以讀取并在當(dāng)前環(huán)境中執(zhí)行腳本,同時(shí)還可返回腳本中最后一個(gè)命令的返回狀態(tài);如果沒有返回值則返回0,代表執(zhí)行成功;如果未找到指定的腳本則返回false
7.別名
alias可用于創(chuàng)建命令的別名,若直接輸入該命令且不帶任何參數(shù),則列出當(dāng)前用戶使用了別名的命令。
自定義別名,比如說一般的關(guān)機(jī)命令是shutdown -h now,寫起來比較長(zhǎng),這時(shí)可以重新定義一個(gè)自己專屬的關(guān)機(jī)命令
[root@localhost ~]# alias myshutdown='shutdown -h now'
不過這種方式在重新登陸之后會(huì)失效,如果想要用就生效,需要將該配置寫在用戶家目錄中的.bashrc文件中。
[root@localhost ~]# less .bashrc
.bashrc
User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
刪除別名
unalias,該命令用于刪除當(dāng)前shell環(huán)境中的別名
第一種刪除:unalias 某個(gè)命令的別名
第二種刪除:unalias -a 這個(gè)刪除當(dāng)前shell環(huán)境中所有的別名
8.任務(wù)前后臺(tái)切換:bg、fg、jobs
該命令用于將任務(wù)放置后臺(tái)運(yùn)行,一般會(huì)與ctrl+z、fg、&符號(hào)聯(lián)合使用。典型的使用場(chǎng)景是運(yùn)行比較耗時(shí)的任務(wù)。比如打包某個(gè)占用較大空間的目錄,若在前臺(tái)執(zhí)行,那么在它完成之前會(huì)一直占用當(dāng)前的終端,而導(dǎo)致無法執(zhí)行其他任務(wù),此時(shí)就應(yīng)該將這類任務(wù)放置后臺(tái)
ctrl+z:組合鍵用于暫停前臺(tái)任務(wù)
jobs:查看暫停的任務(wù)
&:將任務(wù)放置后臺(tái)運(yùn)行,如果預(yù)知某個(gè)任務(wù)耗時(shí)很久,可以一開始就將命令放入后臺(tái)運(yùn)行
fg 1:將后臺(tái)編號(hào)為1的任務(wù)放到當(dāng)前運(yùn)行
9.聲明變量:declare、typeset
這兩個(gè)命令的作用是用來生命變量的
declare -i聲明整型變量
[root@localhost ~]# declare -i num1=1
declare -r 聲明變量為只讀
[root@localhost ~]# declare -r num2=2
[root@localhost ~]# num2=3
bash: num2: readonly variable
10.echo
默認(rèn)情況下,echo會(huì)隱藏-e參數(shù)(禁止解釋打印反斜杠轉(zhuǎn)義的字符)。比如"\n"代表換行,使用echo打印"\n"時(shí),只會(huì)把"\n"當(dāng)作普通字符處理。如果要打印轉(zhuǎn)義字符,則需要通過使用-e參數(shù)來允許。
[root@localhost ~]# echo '\n'
\n
[root@localhost ~]# echo -e '\n'
[root@localhost ~]#
11.跳出循環(huán):break
從一個(gè)循環(huán)(for、while、until、select)中退出。break后可以跟一個(gè)數(shù)字n,代表跳出n層循環(huán),n必須大于1,如果n比當(dāng)前循環(huán)層數(shù)還要大,則跳出所有循環(huán)。
12.循環(huán)控制:continue
停止當(dāng)前循環(huán),并執(zhí)行外層循環(huán)(for、while、until、select)的下一次循環(huán)。continue后可以跟一個(gè)數(shù)字n,代表跳至外部第n層循環(huán),n必須大于1,如果n比當(dāng)前循環(huán)層數(shù)還要大,則跳至最外層的循環(huán)。
13.eval
將所跟參數(shù)作為shell的輸入,并執(zhí)行產(chǎn)生的命令
用法例一:將字符串解析成命令執(zhí)行
[root@localhost shell_learning]# cmd="ls -l /etc/passwd"
[root@localhost shell_learning]# eval $cmd
-rw-r--r-- 1 root root 2857 Jun 11 14:52 /etc/passwd
用法例二:程序運(yùn)行中根據(jù)某個(gè)變量確定實(shí)際的變量名
[root@localhost shell_learning]# name1=john
[root@localhost shell_learning]# name2=wang
[root@localhost shell_learning]# num=1
[root@localhost shell_learning]# eval echo "$"name$num
john
用法例三:將某個(gè)變量的值當(dāng)作另一個(gè)變量名并給其賦值
[root@localhost shell_learning]# name1=john
[root@localhost shell_learning]# name2=wang
[root@localhost shell_learning]# eval $name1="$name2"
[root@localhost shell_learning]# echo $john
wang
14.執(zhí)行命令來取代當(dāng)前的shell:exec
內(nèi)建命令exec并不啟動(dòng)新的shell,而是用要被執(zhí)行的命令替換當(dāng)前的shell進(jìn)程,并且將老進(jìn)程的環(huán)境清理掉,而且exec命令后的其他命令將不再執(zhí)行。假設(shè)在一個(gè)shell里面執(zhí)行exec echo "hello"命令,那么打印hello之后終端就會(huì)斷開(xshell)或者terminal直接退出(linux中的偽終端)。
為了避免上述情況,一般將exec命令放到一個(gè)shell腳本里面,由主腳本調(diào)用這個(gè)腳本,主腳本在調(diào)用子腳本執(zhí)行時(shí),當(dāng)執(zhí)行到exec后,該子腳本進(jìn)程就被替換成相應(yīng)的exec的命令。exec的典型用法是與find聯(lián)合使用,用find找出符合匹配的文件,然后交給exec處理。
[root@localhost ~]# find / -name ".conf" -exec ls -l {} ;
{}與\之間要有空格
15.退出shell:exit
在shell腳本中使用exit代表退出當(dāng)前腳本,該命令可以接受的參數(shù)是一個(gè)狀態(tài)值n,代表退出的狀態(tài),下面的腳本什么都不會(huì)做,一旦運(yùn)行就以狀態(tài)值為5退出。如果不指定,默認(rèn)狀態(tài)值是0。
[root@localhost ~]# vim exit.sh
[root@localhost ~]# sh exit.sh
[root@localhost ~]# echo $?
5
16.使變量能被子shell識(shí)別:export
用戶登陸到系統(tǒng)之后,系統(tǒng)將啟動(dòng)一個(gè)shell,用戶可以在該shell中聲明變量,也可以創(chuàng)建并運(yùn)行shell腳本。在父shell中創(chuàng)建的變量時(shí),這些變量并不會(huì)被其他子shell進(jìn)程所知,也就是說變量默認(rèn)情況下是"私有"的,或稱"局部變量"。使用export命令可以將變量導(dǎo)出,使得該shell的子shell都可以使用該變量,這個(gè)過程稱為變量輸出。
[root@localhost ~]# cat export.sh
!/bin/bash
echo $var
[root@localhost ~]# var=100
[root@localhost ~]# echo $var
100
[root@localhost ~]# sh export.sh
export之后,子shell就能訪問父shell里面$var的值了
[root@localhost ~]# export var=100
[root@localhost ~]# echo $var
100
[root@localhost ~]# sh export.sh
100
需要注意的一點(diǎn),子shell讀取到父shell中變量var的值,但這只是值的傳遞。如果在子shell中嘗試修改變量var的值,改變的只是var在子shell中的值,并不會(huì)影響父shell中var的值
17.整數(shù)運(yùn)算
[root@localhost ~]# let i=2+2
[root@localhost ~]# echo $i
4
求餘
[root@localhost ~]# let M=15%7
[root@localhost ~]# echo $M
1
次方
[root@localhost ~]# let N=2**3
[root@localhost ~]# echo $N
8
自加一
[root@localhost ~]# i=1
[root@localhost ~]# let i++
[root@localhost ~]# echo $i
2
自加十
[root@localhost ~]# echo $i
2
[root@localhost ~]# let i+=10
[root@localhost ~]# echo $i
12
自乘十
[root@localhost ~]# let i*=2
[root@localhost ~]# echo $i
24
自除六
[root@localhost ~]# let i/=6
[root@localhost ~]# echo $i
4
18.聲明局部變量:local
用於在腳本內(nèi)定義局部變量,典型的用法是用於函數(shù)體內(nèi),其作用域也在聲明該變量的函數(shù)體中。如果試圖在函數(shù)外使用local聲明變量,則會(huì)提示錯(cuò)誤
19.從標(biāo)準(zhǔn)輸入讀取一行到變量:read
有時(shí)候我們開發(fā)的腳本必須具有交互性,也就是在運(yùn)行過程依賴人工輸入才能繼續(xù)。
[root@localhost shell_learning]# cat read.sh
!/bin/bash
declare N
echo "12 bottles of beer in a box"
echo -n "How many box do you want:"
read N
echo "$((N*12)) bottle in total"
[root@localhost shell_learning]# sh read.sh
12 bottles of beer in a box
How many box do you want3
36bottle in total
優(yōu)化
!/bin/bash
echo "12 bottles of beer in a box"
read -p "How many box do you want:" N
echo "$((N*12)) bottle in total"
20.定義函數(shù)返回值:return
常見的用法是返回一個(gè)數(shù)字return n,如果沒有指定n值,則返回狀態(tài)是函數(shù)體中執(zhí)行的最后一個(gè)命令的退出狀態(tài)
[root@localhost ~]# cat return.sh
!/bin/bash
function fun_01 {
return 1
}
fun_01
echo $?
[root@localhost ~]# bash return.sh
1
21.向左移動(dòng)位置參數(shù):shift
一個(gè)腳本在運(yùn)行時(shí)可以接收,從左到有第一個(gè)參數(shù)被記作$1,第二個(gè)參數(shù)為$2,以此類推。所有參數(shù)記作$@或$*
參數(shù)總個(gè)數(shù)記為$#,腳本本身記作$0
shift命令可以對(duì)腳本的參數(shù)做"偏移"操作。假設(shè)腳本有A B C這三個(gè)參數(shù),那么$1為A,$2為B,$3為C;shift一次
之后$1為B,$2為C。再shift一次,$1為C
22.顯示并設(shè)置進(jìn)程資源限度:ulimit
軟限制不能高于硬限制
查看系統(tǒng)軟限制
[root@localhost ~]# ulimit -a
core file size (blocks, -c) 0 文件大小
data seg size (kbytes, -d) unlimited 數(shù)據(jù)段大小
scheduling priority (-e) 0 調(diào)度優(yōu)先級(jí)
file size (blocks, -f) unlimited 創(chuàng)建文件的大小
pending signals (-i) 63121 掛起的信號(hào)數(shù)量
max locked memory (kbytes, -l) 64 最大鎖定內(nèi)存的值
max memory size (kbytes, -m) unlimited 最大可用的常駐內(nèi)存值
open files (-n) 1024 最大的文件打開數(shù)
pipe size (512 bytes, -p) 8 管道最大緩沖區(qū)的值
POSIX message queues (bytes, -q) 819200 消息隊(duì)列的最大值
real-time priority (-r) 0 程序的實(shí)時(shí)性優(yōu)先級(jí)
stack size (kbytes, -s) 8192 棧大小
cpu time (seconds, -t) unlimited 最大cpu占用時(shí)間
max user processes (-u) 63121 用戶最大進(jìn)程數(shù)
virtual memory (kbytes, -v) unlimited 最大虛擬內(nèi)存
file locks (-x) unlimited 文件鎖
設(shè)置最大文件打開數(shù)(命令行設(shè)置,在系統(tǒng)重啟后就失效)
同時(shí)設(shè)置軟限制和硬限制
[root@localhost ~]# ulimit -n 4096
僅設(shè)置軟連接
[root@localhost ~]# ulimit -S -n 4096
僅設(shè)置硬連接
[root@localhost ~]# ulimit -H -n 4096
修改配置文件(永久生效)
格式:
可用item
can be one of the following:
- core - limits the core file size (KB)
- data - max data size (KB)
- fsize - maximum filesize (KB)
- memlock - max locked-in-memory address space (KB)
- nofile - max number of open file descriptors 最大文件打開數(shù)
- rss - max resident set size (KB) 最大常駐內(nèi)存值
- stack - max stack size (KB)
- cpu - max CPU time (MIN)
- nproc - max number of processes 最大進(jìn)程數(shù)
- as - address space limit (KB) 虛擬地址空間
- maxlogins - max number of logins for this user
- maxsyslogins - max number of logins on the system
- priority - the priority to run user process with
- locks - max number of file locks the user can hold
- sigpending - max number of pending signals
- msgqueue - max memory used by POSIX message queues (bytes)
- nice - max nice priority allowed to raise to values: [-20, 19]
- rtprio - max realtime priority
23.測(cè)試表達(dá)式:test
根據(jù)測(cè)試結(jié)果返回0(測(cè)試失敗)或1(測(cè)試成功)
查看系統(tǒng)中可用的shell
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
修改用戶登陸的shell
chsh 用戶名
[root@localhost ~]# chsh liangjiongyao
Changing shell for liangjiongyao.
New shell [/bin/bash]: /bin/sh
Shell changed.
不加用戶名默認(rèn)就是root
其實(shí)修改的是/etc/passwd里面的最后一列
liangjiongyao?1000:1000:liangjiongyao:/home/liangjiongyao:/bin/sh
變量賦值和取值
注意點(diǎn):變量名和變量值之間用等號(hào)緊緊相連,之間沒有任何空格--skip-broken
[root@localhost ~]# name=john
[root@localhost ~]# echo $name
john
[root@localhost ~]# name="joe"
[root@localhost ~]# echo $name
joe
當(dāng)變量有空格時(shí)必須用引號(hào)括起,否則會(huì)報(bào)錯(cuò)
[root@localhost ~]# name=john wang
bash: wang: command not found...
[root@localhost ~]# name="john wang"
[root@localhost ~]# echo $name
john wang
注意點(diǎn):獲取變量值的一種比較保險(xiǎn)的方式
[root@localhost ~]# name="john wang"
[root@localhost ~]# echo ${name}
john wang
[root@localhost ~]# name="sue"
[root@localhost ~]# echo $namehello #變量namehello沒有定義
[root@localhost ~]# echo ${name}hello
suehello
注意點(diǎn):如果變量值引用的是其他變量,則必須使用雙引號(hào)。因?yàn)閱我?hào)會(huì)阻止shell解釋變量
[root@localhost ~]# name="john"
[root@localhost ~]# name1="$name"
[root@localhost ~]# echo $name1
john
[root@localhost ~]# name2='$name'
[root@localhost ~]# echo $name2
$name
因?yàn)閟hell具有弱變量的特性,因此即便在沒有預(yù)先聲明變量的好時(shí)候也是可以引用的。如果在腳本中引用沒有定義的
變量,導(dǎo)致腳本異常,那么排查起來也很困難。因此必須使腳本遵循"先聲明再使用"。
[root@localhost ~]# echo $undefinedVar
[root@localhost ~]# shopt -o -s nounset
[root@localhost ~]# echo $undefinedVar
bash: undefinedVar: unbound variable
取消變量
就是將變量從內(nèi)存中釋放,使用的命令是unset,后面跟變量名,函數(shù)也是可以被取消的。
[root@localhost ~]# name=john
[root@localhost ~]# echo $name
john
[root@localhost ~]# unset name
[root@localhost ~]# echo $name
bash: name: unbound variable
取消函數(shù)
[root@localhost liangjiongyao]# cat test
!/bin/bash
unset_function(){
echo "Hello World"
}
unset unset_function
unset_function
[root@localhost liangjiongyao]# bash test
test: line 7: unset_function: command not found
命令的返回值
linux中規(guī)定正常退出的命令和腳本應(yīng)該以0作為其返回值,任何非0的返回值都表示命令未正確退出或未正常執(zhí)行
[root@localhost liangjiongyao]# ifco
bash: ifco: command not found...
[root@localhost liangjiongyao]# echo $?
127
[root@localhost liangjiongyao]# ping 1
connect: Invalid argument
[root@localhost liangjiongyao]# echo $?
2
數(shù)組
數(shù)組是一種特殊的數(shù)據(jù)結(jié)構(gòu),其中的每一項(xiàng)被稱為一個(gè)元素,對(duì)于每個(gè)元素,都可以用索引方式取出元素的值。shell中數(shù)組對(duì)元組個(gè)數(shù)沒有限制,
但只支持一維數(shù)組。
定義數(shù)組
[root@localhost liangjiongyao]# declare -a Array
[root@localhost liangjiongyao]# Array[0]=0
[root@localhost liangjiongyao]# Array[1]=1
[root@localhost liangjiongyao]# Array[2]="HelloWorld"
創(chuàng)建時(shí)賦值
[root@localhost liangjiongyao]# declare -a Name=('john''sue')
不使用declare關(guān)鍵字創(chuàng)建數(shù)組
[root@localhost liangjiongyao]# Name=('john''sue')
對(duì)特定的元素賦值
[root@localhost liangjiongyao]# Score=([3]=3 5=[5] [7]=7)
數(shù)組操作
取值:${數(shù)組名[索引]}
[root@localhost liangjiongyao]# echo ${Array[0]}
0
[root@localhost liangjiongyao]# echo ${Array[2]}
HelloWorld
[root@localhost liangjiongyao]# echo ${Array[1]}
1
一次性取出數(shù)組中所有元素的值
[root@localhost liangjiongyao]# echo ${Array[@]}
0 1 HelloWorld #以空格隔開的元素值
[root@localhost liangjiongyao]# echo ${Array[*]}
0 1 HelloWorld #一整個(gè)字符串
獲取數(shù)組的長(zhǎng)度(即元素個(gè)數(shù))
[root@localhost liangjiongyao]# echo ${#Array[*]}
3
[root@localhost liangjiongyao]# echo ${#Array[@]}
3
如果某個(gè)元素是字符串,還可以通過指定索引的方式獲得該元素的長(zhǎng)度
[root@localhost liangjiongyao]# echo ${#Array[2]}
10
[root@localhost liangjiongyao]# echo ${Array[2]}
HelloWorld
取出數(shù)組的第一、第二個(gè)元素
[root@localhost liangjiongyao]# echo ${Array[@]:1:2}
1 HelloWorld
取出數(shù)組的第二個(gè)元素中的第0~5個(gè)字符
[root@localhost liangjiongyao]# echo ${Array[2]:0:5}
Hello
連接數(shù)組:將若干個(gè)數(shù)組進(jìn)行拼接操作
[root@localhost liangjiongyao]# Conn=(${Array[@]} ${Name[@]})
[root@localhost liangjiongyao]# echo ${Conn[@]}
0 1 HelloWorld johnsue
替換元素:將數(shù)組內(nèi)某個(gè)元素的值替換成其他值
[root@localhost liangjiongyao]# Array=(${Array[@]/HelloWorld/HelloJohn})
[root@localhost liangjiongyao]# echo ${Array[@]}
0 1 HelloJohn
取消數(shù)組或元素
取消數(shù)組中的一個(gè)元素
[root@localhost liangjiongyao]# unset Array[1]
[root@localhost liangjiongyao]# echo ${Array[@]}
0 HelloJohn
取消整個(gè)數(shù)組
[root@localhost liangjiongyao]# unset Array
[root@localhost liangjiongyao]# echo ${Array[@]}
本行為空
只讀變量
通過readonly內(nèi)建命令創(chuàng)建的變量
[root@localhost liangjiongyao]# readonly ro=100
[root@localhost liangjiongyao]# ro=200
bash: ro: readonly variable
[root@localhost liangjiongyao]# declare -r rp=100
[root@localhost liangjiongyao]# rp=200
bash: rp: readonly variable
變量的作用域
又稱“名稱空間”,表示變量的上下文。相同的變量可以在多個(gè)命名空間中定義,并且彼此之間互不相干。
就像A班有個(gè)小明,B班也有個(gè)小明,雖然他們都叫小明但是由于所在的班級(jí)不一樣(對(duì)應(yīng)于命名空間),所以不會(huì)造成混亂
2018-08-23 晚
控制字符
即ctrl+key組合鍵一起使用,用于修改終端或文本顯示,一般在命令行下使用,腳本中不能使用。
ctrl+L 清屏
ctrl+Z 暫停前臺(tái)作業(yè)
ctrl+U 刪除光標(biāo)到行首的所有字符
測(cè)試結(jié)構(gòu)
格式一:test expression是一個(gè)表達(dá)式,可以是算術(shù)比較、字符串比較、文本和文件屬性比較等
格式二:使用[ expression ] #推薦,易于與if、case、while這些條件判斷的關(guān)鍵字連用
[root@localhost yum.repos.d]# test -e /var/log/messages
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# test -e /var/log/messages01
[root@localhost yum.repos.d]# echo $?
1
[root@localhost yum.repos.d]# [ -e /var/log/messages ]
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# [ -e /var/log/messages01 ]
[root@localhost yum.repos.d]# echo $?
1
文件測(cè)試符
-b 當(dāng)文件存在且是個(gè)塊文件時(shí)返回真,否則為假
-c 當(dāng)文件存在且是個(gè)字符設(shè)備時(shí)返回真,否則為假
-d 當(dāng)文件存在且是個(gè)目錄時(shí)返回真,否則為假
-e 當(dāng)文件或者目錄存在時(shí)返回真,否則為假
-f 當(dāng)文件存在且為普通文件時(shí)返回真,否則為假
-x 當(dāng)文件存在且為可執(zhí)行文件時(shí)返回真,否則為假
-s 當(dāng)文件存在且大小不為0時(shí)返回真,否則為假
-S 當(dāng)文件存在且為socket文件時(shí)返回真,否則為假
-r 當(dāng)文件存在且為可讀文件時(shí)返回真,否則為假
-w 當(dāng)文件存在且為可寫文件時(shí)返回真,否則為假
-x 當(dāng)文件存在且為可執(zhí)行文件時(shí)返回真,否則為假
FILE1 -nt FILE2 當(dāng)FILE1比FILE2新時(shí)返回真,否則為假
FILE1 -ot FILE2 當(dāng)FILE1比FILE2舊時(shí)返回真,否則為假
文件新舊的比較的主要使用場(chǎng)景是判斷文件是否被更新或增量備份時(shí),用于判斷一段時(shí)間以來更新過的文件
字符串測(cè)試
-z "string" 字符串string為空時(shí)返回真,否則為假
-n "string" 字符串string非空時(shí)返回真,否則為假
"string1" = "string1" string1和string2相同時(shí)返回真,否則為假
"string1" != "string1" string1和string2不相同時(shí)返回真,否則為假
"string1" > "string2" 按照字典排序,字符串string1排在string2之前返回真,否則為假
"string1" < "string2" 按照字典排序,字符串string1排在string2之后返回真,否則為假
[root@localhost yum.repos.d]# str1=""
[root@localhost yum.repos.d]# str2="hello"
[root@localhost yum.repos.d]# [ "$str1" > "$str2" ] #大于號(hào)需要轉(zhuǎn)義
[root@localhost yum.repos.d]# echo $?
1
[root@localhost yum.repos.d]# [[ "$str1" > "$str2" ]] #不向轉(zhuǎn)義就用[[]]
[root@localhost yum.repos.d]# echo $?
1
整數(shù)測(cè)試
-eq 等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
-ne 不等于
[root@localhost yum.repos.d]# num1=10
[root@localhost yum.repos.d]# num2=10
[root@localhost yum.repos.d]# num3=9
[root@localhost yum.repos.d]# num4=11
[root@localhost yum.repos.d]# [ "$num1" -eq "$num2" ]
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# [ "$num1" -gt "$num3" ]
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# [ "$num1" -ge "$num2" ]
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# [ "$num1" -le "$num2" ]
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# [ "$num1" -ne "$num3" ]
[root@localhost yum.repos.d]# echo $?
0
邏輯測(cè)試符和邏輯運(yùn)算符
邏輯測(cè)試用于連接多個(gè)測(cè)試條件,并返回整個(gè)表達(dá)式的值
邏輯非的使用
測(cè)試值為真的表達(dá)式在使用邏輯非后,表達(dá)式變?yōu)榧?#xff0c;反之亦然
[root@localhost yum.repos.d]# [ ! -e /var/log/messages ]
[root@localhost yum.repos.d]# echo $?
1
邏輯與使用
表達(dá)式都為真,整個(gè)表達(dá)式才返回真,否則返回假
[root@localhost yum.repos.d]# [ -e /var/log/messages -a -e /var/log/messages ]
[root@localhost yum.repos.d]# echo $?
0
[root@localhost yum.repos.d]# [ -e /var/log/messages -a -e /var/log/messages01 ]
[root@localhost yum.repos.d]# echo $?
1
邏輯或的使用
測(cè)試表達(dá)式中只要有真,則整個(gè)表達(dá)式返回真
[root@localhost yum.repos.d]# [ -e /var/log/messages -o -e /var/log/messages01 ]
[root@localhost yum.repos.d]# echo $?
0
邏輯運(yùn)算符
! 非
&& 與
|| 或
[root@localhost yum.repos.d]# ! [ -e /var/log/messages ]
[root@localhost yum.repos.d]# echo $?
1
[root@localhost yum.repos.d]# [ -e /var/log/messages ]&&[ -e /var/log/messages01 ]
[root@localhost yum.repos.d]# echo $?
1
[root@localhost yum.repos.d]# [ -e /var/log/messages ]||[ -e /var/log/messages01 ]
[root@localhost yum.repos.d]# echo $?
0
判斷
if判斷結(jié)構(gòu)
if exp;then
command
......
fi
[root@localhost liangjiongyao]# cat score01.sh
!/bin/bash
echo -n "please input a score:"
read score
if [ "$score" -lt 60 ];then
echo "C"
fi
if [ "$score" -lt 80 -a "$score" -ge 60 ];then
echo "B"
fi
if [ "$score" -ge 80 ];then
echo "A"
fi
分支(if/else)
if exp;then
command
else
command
fi
[root@localhost liangjiongyao]# cat check_file.sh
!/bin/bash
FILE=/var/log/messages
if [ -e $FILE ];then
echo "$FILE exist"
else
echo "$FILE not exist"
fi
if/elif/else判斷結(jié)構(gòu)
if exp1;then
command
elif exp2;then
command
else
command
fi
優(yōu)化score01.sh
[root@localhost liangjiongyao]# cat score02.sh
!/bin/bash
echo -n "please input a score:"
read score
if [ "$score" -lt 60 ];then
echo "C"
elif [ "$score" -lt 80 -a "$score" -ge 60 ];then
echo "B"
else
echo "A"
fi
case判斷結(jié)構(gòu)
與if/elif/else一樣,可用于多種情況下的分支選擇,語法如下:
case VAR in
var1)command1;;
var2)command1;;
var3)command1;;
var4)command1;;
...
esac
原理為從上到下依次比較VAR和var1、var2、var3的值是否相等,如果匹配相等則執(zhí)行后面的命令語句,在無一匹配的情況下
匹配最后默認(rèn)的*,并執(zhí)行后面的默認(rèn)命令。需要注意的是,var1 var2 var3等這些值只能是常量或正則表達(dá)式
[root@localhost liangjiongyao]# cat os_type.sh
!/bin/bash
OS=uname -s
case "$OS" in
FreeBSD) echo "this is Cygwin";;
SunOS) echo "this is Solaris";;
AIX) echo "this is Minix";;
Linux) echo "this is Linux";;
*) echo "Failed to identify this OS";;
esac
2018-08-25
帶參數(shù)的函數(shù)
位置參數(shù)
[root@localhost liangjiongyao]# cat checkFileExist_v2.sh
!/bin/bash
function checkFileExist(){
if [ -f $1 ];then
return 0
else
return 1
fi
}
checkFileExist $1
if [ $? -eq 0 ];then
echo "$1 exist"
else
echo "$1 not exist"
fi
使用的時(shí)候直接向腳本傳遞文件全路經(jīng)的方式傳遞參數(shù)
[root@localhost liangjiongyao]# bash checkFileExist_v2.sh /etc/notExist
/etc/notExist not exist
[root@localhost liangjiongyao]# bash checkFileExist_v2.sh /etc/passwd
/etc/passwd exist
移動(dòng)位置參數(shù)
前面有提到,shift命令可讓位置參數(shù)左移一位
[root@localhost liangjiongyao]# cat shift_03.sh
!/bin/bash
until [ $# -eq 0 ]
do
echo "Now $1 is: $1,total parameter is:$#"
shift
done
[root@localhost liangjiongyao]# bash shift_03.sh a b c d
Now $1 is: a,total parameter is:4
Now $1 is: b,total parameter is:3
Now $1 is: c,total parameter is:2
Now $1 is: d,total parameter is:1
如果在shift加數(shù)字n,則位置參數(shù)將會(huì)每次移動(dòng)n位
下面利用shift計(jì)算腳本中所有參數(shù)的和
[root@localhost liangjiongyao]# cat shift_04.sh
!/bin/bash
tatal=0
until [ $# -eq 0 ]
do
let "tatol=tatol + $1"
shift
done
echo $tatol
[root@localhost liangjiongyao]# bash shift_04.sh 1 2 3 4
10
函數(shù)庫(kù)
對(duì)于某些常用的功能,必須考慮將其獨(dú)立出來,集中存放在一些獨(dú)立的文件中,這些文件就被稱為“函數(shù)庫(kù)”。
函數(shù)庫(kù)的本質(zhì)也是“函數(shù)”,所以它的定義方式和普通函數(shù)沒有任何區(qū)別,但為了和一般函數(shù)區(qū)分開來,在實(shí)踐中建議函數(shù)庫(kù)
使用下劃線開頭。
自定義函數(shù)庫(kù)
[root@localhost liangjiongyao]# cat lib01.sh
!/bin/bash
_checkFileExist(){
if [ -f $1 ];then
echo "$1 exist"
else
echo "$1 not exist"
fi
}
其他腳本在希望直接調(diào)用_checkFileExist函數(shù)時(shí),可以通過直接加載lib01.sh函數(shù)庫(kù)的方式實(shí)現(xiàn)。加載方式有如下兩種:
使用“點(diǎn)”命令
[root@localhost liangjiongyao]# ./PATH/TO/LIB
使用source命令
[root@localhost liangjiongyao]# source /PATH/TO/LIB
假設(shè)現(xiàn)在有個(gè)腳本想要直接調(diào)用_checkFileExist函數(shù),可以通過加載lib01.sh函數(shù)庫(kù)來實(shí)現(xiàn)。
[root@localhost liangjiongyao]# cat lib01.sh
!/bin/bash
_checkFileExist(){
if [ -f $1 ];then
echo "$1 exist"
else
echo "$1 not exist"
fi
}
[root@localhost liangjiongyao]# cat callLib01.sh
!/bin/bash
source ./lib01.sh #當(dāng)前路徑下
_checkFileExist /etc/notExistFile
_checkFileExist /etc/passwd
[root@localhost liangjiongyao]# bash callLib01.sh
/etc/notExistFile not exist
/etc/passwd exist
function函數(shù)庫(kù)
位置:/etc/init.d/functions
function函數(shù)庫(kù)中的常用函數(shù)
checkpid() 檢查某個(gè)PID是否存在
daemon() 以daemon方式啟動(dòng)某個(gè)服務(wù)
killproc() 停止某個(gè)進(jìn)程
pidfileofproc() 檢查某個(gè)進(jìn)程的PID文件
pidofproc() 檢查某個(gè)進(jìn)程的PID
status() 判斷某個(gè)服務(wù)的狀態(tài)
echo_success() 打印OK
echo_failure() 打印FAILED
echo_passed() 打印PASSED
echo_warning() 打印Waring
success() 打印OK并記錄日志
failure() 打印FAILED并記錄日志
passed() 打印PASSED并記錄日志
warning() 打印Waring并記錄日志
action() 執(zhí)行給定的命令,并根據(jù)執(zhí)行結(jié)果打印信息
strstr() 檢查$1字符串中是否含有$2字符串
comfirm() 提示是否啟動(dòng)某個(gè)服務(wù)
遞歸函數(shù)
在函數(shù)體中繼續(xù)調(diào)用函數(shù)自身,但是遞歸函數(shù)不可能無限遞歸下去,所以它一定要有結(jié)束遞歸的條件,當(dāng)滿足該條件時(shí),遞歸就會(huì)終止。
結(jié)構(gòu)如下:
function recursion(){
recursion
conditionThatEndTheRecursion #停止遞歸的條件
}
使用-x可以觀察腳本運(yùn)行過程
重定向
所謂“重定向”,就是將原本應(yīng)該從標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)輸入的數(shù)據(jù),改由其他文件或設(shè)備輸入;或?qū)⒃緫?yīng)該輸出到標(biāo)準(zhǔn)輸出設(shè)備(顯示器)的內(nèi)容,
改而輸出到其他文件或設(shè)備上。
文件標(biāo)識(shí)符和標(biāo)準(zhǔn)輸入輸出
文件標(biāo)識(shí)符是重定向中一個(gè)很重要的一個(gè)概念,linux使用0到9的整數(shù)指明了與特定進(jìn)程相關(guān)的數(shù)據(jù)流,系統(tǒng)在啟動(dòng)一個(gè)進(jìn)程的同時(shí)會(huì)為該進(jìn)程打開上個(gè)文件:
標(biāo)準(zhǔn)輸入(stdin)、標(biāo)準(zhǔn)輸出(stdout)、標(biāo)準(zhǔn)錯(cuò)誤輸出(stderr),分別用文件標(biāo)識(shí)符0、1、2來標(biāo)識(shí)。如果要為進(jìn)程打開其他的輸入輸出,則需要從整數(shù)3開始標(biāo)識(shí)。
默認(rèn)情況下,標(biāo)準(zhǔn)輸入為鍵盤,標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出為顯示器。
I/O重定向
I/O重定向可以將任何文件、命令、腳本、程序或腳本的輸出重定向到另外一個(gè)文件、命令、程序或腳本
標(biāo)準(zhǔn)輸出覆蓋重定向,默認(rèn)將文件標(biāo)識(shí)符為1的內(nèi)容重定向到指定文件中
標(biāo)準(zhǔn)輸出追加重定向
& 標(biāo)準(zhǔn)輸出重定向
< 標(biāo)準(zhǔn)輸入重定向
| 管道
如果命令由于各種原因出錯(cuò)時(shí)所產(chǎn)生的錯(cuò)誤輸出,其文件標(biāo)識(shí)符為2,可以將其重定向到文件中就不會(huì)出現(xiàn)在顯示器上了
[root@localhost liangjiongyao]# ls -l /usr/noexc 2> 1.txt
[root@localhost liangjiongyao]# cat 1.txt
ls: cannot access /usr/noexc: No such file or directory
標(biāo)識(shí)輸出重定向:>&
將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤同時(shí)定向到同一個(gè)文件中
[root@localhost liangjiongyao]# command > stdout_stderr.txt1 2>&1
將錯(cuò)誤輸出重定向到“宇宙黑洞”
[root@localhost liangjiongyao]# command > stdout_stderr.txt2 2>/dev/null
標(biāo)準(zhǔn)輸入重定向:<
從文件讀取內(nèi)容輸入,也就是將文件內(nèi)容寫入標(biāo)準(zhǔn)輸入中
[root@localhost ~]# cat < helloworld.txt
hello
world
[root@localhost ~]# cat helloworld.txt
hello
world
排序
[root@localhost ~]# cat fruit01.txt
banana
carrot
apple
[root@localhost ~]# sort < fruit01.txt
apple
banana
carrot
2018-08-26 晚
for循環(huán)在按行讀取文件內(nèi)容時(shí),任何空白字符都可以作為其讀取的分隔符;而while的按行讀取就沒有這個(gè)問題,因?yàn)閣hile是使用換行符
作為行標(biāo)記的
用cut截取第一列, -f1是第一列的意思,-d是指定分隔符
[root@localhost ~]# cat user_info.txt | cut -f1 -d' '
user001
user002
user003
非交互式給用戶創(chuàng)建密碼
echo "password" | passwd --stdin xpp
ftp服務(wù)端配置文件 /etc/vsftpd/vsftpd.conf中
anon_upload_enable=YES #允許匿名用戶上傳文件
anon_other_write_enable=YES #允許匿名用戶覆蓋同名文件
利用md5sum校驗(yàn)文件是否被修改
[root@localhost ~]# md5sum /etc/passwd > passwd.md5
[root@localhost ~]# md5sum -c passwd.md5
/etc/passwd: OK #如果沒有被修改,則打印OK
[root@localhost ~]# useradd xpp
[root@localhost ~]# md5sum -c passwd.md5
/etc/passwd: FAILED
md5sum: WARNING: 1 computed checksum did NOT match
[root@localhost ~]#
利用ssh遠(yuǎn)程執(zhí)行命令
[root@localhost ~]# ssh root@192.168.3.2 "echo $HOSTNAME"
利用腳本自動(dòng)執(zhí)行ssh-copy-id
[root@localhost ~]# cat expect_ssh_copy_id.sh
!/bin/bash
PASS=$1
IP=$2
auto_ssh_copy_id() {
expect -c "set timeout -1;
spawn /usr/bin/ssh-copy-id -i /root/.ssh/id_rsa.pub root@$2;
expect {
(yes/no) {send -- yes\r;exp_continue;}
Password: {send -- $1\r;exp_continue;}
eof {exit 0;}
}";
}
2018-08-27晚
iptables防火墻
4表:filter表(用于過濾)、nat表(地址或端口映射)、mangle表(對(duì)特定數(shù)據(jù)包的修改)、raw表
5鏈:prerouting 數(shù)據(jù)包進(jìn)入路由決策之前
input 路由決策為本機(jī)的數(shù)據(jù)包
forward 路由決策不是本機(jī)的數(shù)據(jù)包
output 由本機(jī)產(chǎn)生的向外發(fā)送的數(shù)據(jù)包
postrouting 發(fā)送給網(wǎng)卡之前的數(shù)據(jù)包
[root@localhost ~]# ssh root@ceph-deploy
The authenticity of host 'ceph-deploy (192.168.101.2)' can't be established.
ECDSA key fingerprint is SHA256:UKNbnhKXfY/fODVDTQMcFyubYQdC0CqXuPf7hTzreHo.
ECDSA key fingerprint is MD5:e0:a9:1b:7c:2a:f0:0c:fc:01:7c:6b:7f:27:7a:5d:58.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ceph-deploy' (ECDSA) to the list of known hosts.
Last login: Wed Aug 15 12:23:15 2018 from 192.168.122.1
[root@ceph-deploy ~]# ping www.baidu.com
PING www.a.shifen.com (183.232.231.173) 56(84) bytes of data.
64 bytes from 183.232.231.173 (183.232.231.173): icmp_seq=1 ttl=52 time=6.81 ms
清空所有的規(guī)則
[root@ceph-deploy ~]# iptables -F
刪除所有自定義的鏈
[root@ceph-deploy ~]# iptables -X
丟棄進(jìn)來的數(shù)據(jù)包
[root@ceph-deploy ~]# iptables -P INPUT DROP
[root@localhost ~]# ssh root@ceph-deploy
^C ###連不上了
丟棄出去的數(shù)據(jù)包
[root@ceph-deploy ~]# iptables -P OUTPUT DROP
[root@ceph-deploy ~]# ping www.baidu.com
...... ###ping不通了
[root@ceph-deploy ~]# ping 127.0.0.1
ping:sendmsg: Operation not permitted
......
目前的狀況跟拔掉網(wǎng)線的操作沒什么不同,而且比沒有防火墻更糟糕的是本地?cái)?shù)據(jù)包都無法通信了。因此需要一些策略來保證一些基本功能可用,所以要設(shè)置
以下規(guī)則。
允許icmp包進(jìn)入
iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
允許icmp出去
iptables -A OUTPUT -p icmp --icmp-type any -j ACCEPT
[root@ceph-deploy ~]# ping www.baidu.com
...... ###仍不通
[root@ceph-deploy ~]# ping 127.0.0.1
64 bytes from 127.0.0.1......
[root@ceph-deploy ~]# ping 192.168.122.1 #網(wǎng)關(guān)
64 bytes from 192.168.122.1......
[root@localhost ~]# ping 192.168.122.2 #網(wǎng)關(guān)能ping該主機(jī)
PING 192.168.122.2 (192.168.122.2) 56(84) bytes of data.
64 bytes from 192.168.122.2: icmp_seq=1 ttl=64 time=0.267 ms
[root@localhost ~]# ssh root@192.168.122.2
^C #依舊ssh不上
允許本地?cái)?shù)據(jù)包出
iptables -A OUTPUT -s localhost -d localhost -j ACCEPT
允許本地?cái)?shù)據(jù)包進(jìn)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
允許以建立和相關(guān)的數(shù)據(jù)包進(jìn)入
iptables -A OUTPUT -M state --state ESTABLISHED,RELATED -j ACCEPT
如果是一臺(tái)web服務(wù)器,典型的需要是能訪問80端口,但是就目前的策略而言是無法訪問的,所以需要允許80端口訪問
iptables -A INPUT -p tcp --dport 80 -j ACCEPT #外來數(shù)據(jù)包可以通過本地的80端口進(jìn)來
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #保證發(fā)給對(duì)端的數(shù)據(jù)包包能通過本地80端口出去
這里使用狀態(tài)跟蹤模塊,意思是對(duì)能建立完整的連接以及為了維持該連接需要打開的其他連接所產(chǎn)生的數(shù)據(jù)包都是可以通過防火墻的OUTPUT鏈。
如果需要允許當(dāng)前服務(wù)器訪問其他web服務(wù)器,該怎么辦?只要打開讓數(shù)據(jù)出去的80端口就可以了。
iptables -A OUTPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
如果需要訪問www.baidu.com,就必須要允許域名解釋的數(shù)據(jù)包出去,因?yàn)榉?wù)器訪問該域名之前需要先解釋出它的IP地址
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
由于管理需要ssh到這臺(tái)服務(wù)器,則需要打開22端口
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
如果只能允許一個(gè)固定的IP能ssh到該服務(wù)器的話,上面的語句需要該為
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.10 -j ACCEPT
可能還需要從該服務(wù)器ssh到別的服務(wù)器
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
自定義開機(jī)啟動(dòng)項(xiàng)的init腳本
init腳本是linux系統(tǒng)用于啟動(dòng)系統(tǒng)服務(wù)的腳本,存放路徑為/etc/init.d/。系統(tǒng)在啟動(dòng)時(shí)將根據(jù)當(dāng)前的運(yùn)行等級(jí)確定
運(yùn)行在/etc/rc.d/rcX.d目錄下的腳本(都是到/etc/init.d目錄中的文件軟連接)
init腳本必須接收至少兩個(gè)參數(shù):start和stop,用于啟動(dòng)和停止服務(wù)。建議在寫init腳本時(shí),將各種參數(shù)的執(zhí)行體封裝成函數(shù)的格式。
使用腳本操作MySQL數(shù)據(jù)庫(kù)
查看本地所有數(shù)據(jù)庫(kù)
[root@localhost ~]# mysql -uroot -p123 -e "show databases"
使用腳本
[root@localhost ~]# cat mysql01.sh
!/bin/bash
username="root"
password="123"
cmd="show databases"
mysql -u$username -p$password -e "$cmd"
[root@localhost ~]# bash mysql01.sh
+--------------------+
| Database |
+--------------------+
| information_schema |
| Django_ORM |
| LJY |
| ORM_mutil |
| char_set_test |
| django_demo01 |
| liangjiongyao |
| ljy |
| mysql |
| performance_schema |
| test |
+--------------------+
創(chuàng)建數(shù)據(jù)庫(kù)
create_db_sql="create database ${database}"
mysql -u$username -p$password -e "$create_db_sql"
創(chuàng)建表
create_table_sql="create table ${table}(name varchar(20),id int(10))"
mysql -u$username -p$password $dbname -e "$create_table_sql"
插入數(shù)據(jù)
insert_sql="insert into ${table} values('john',1)"
mysql -u$username -p$password $dbname -e "$insert_sql"
查詢
select_sql="select * from $table"
mysql -u$username -p$password $dbname -e "$select_sql"
更新數(shù)據(jù)
update_sql="upadte $table set id=3"
mysql -u$username -p$password $dbname -e "$update_sql"
刪除數(shù)據(jù)
delete_sql="delete from ${table}"
mysql -u$username -p$password $dbname -e "$delete_sql"
使用here Document執(zhí)行SQL代碼塊
[root@localhost ~]# cat mysql02.sh
!/bin/bash
mysql -uroot -p123 << EOF
create database db01;
use db01;
create table user01(
userid int(20) not null,
username varchar(20) not null,
userpass varchar(20) not null,
age int(10) not null,
primary key(userid)
);
EOF
[[root@localhost ~]# bash mysql02.sh root@localhost ~]# bash mysql02.sh
[root@localhost ~]# bash mysql02.sh
[root@localhost ~]# mysql -uroot -p123 -e "show databases;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| Django_ORM |
| LJY |
| ORM_mutil |
| char_set_test |
| db01 |
| django_demo01 |
| liangjiongyao |
| ljy |
| mysql |
| performance_schema |
| test |
+--------------------+
[root@localhost ~]# mysql -uroot -p123 db01 -e "show tables;"
+----------------+
| Tables_in_db01 |
+----------------+
| user01 |
+----------------+
[root@localhost ~]# mysql -uroot -p123 db01 -e "select * from user01;"
[root@localhost ~]# mysql -uroot -p123 db01 -e "desc user01;"
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| userid | int(20) | NO | PRI | NULL | |
| username | varchar(20) | NO | | NULL | |
| userpass | varchar(20) | NO | | NULL | |
| age | int(10) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
[root@localhost ~]# cat insert.sql | mysql -uroot -p123 db01
[root@localhost ~]# mysql -uroot -p123 db01 -e "select * from user01;"
+--------+----------+----------+-----+
| userid | username | userpass | age |
+--------+----------+----------+-----+
| 1 | ljy | 123 | 23 |
+--------+----------+----------+-----+
[root@localhost ~]# cat insert.sql
insert into user01 values(1,'ljy',123,23)
使用lvm備份mysql數(shù)據(jù)
使用mysqldump或mysqlhotcopy進(jìn)行備份,這種方式往往會(huì)造成數(shù)據(jù)備份不一致的問題。在備份的過程中,當(dāng)備份工具完成了
備份表A的備份之后,在備份表B時(shí),可能A表記錄已經(jīng)發(fā)生了變化,這樣的備份文件實(shí)際上是無法用于數(shù)據(jù)庫(kù)恢復(fù)。解決這個(gè)問題的方法是在整個(gè)備份過程中鎖定表,
直至備份結(jié)束,但這會(huì)影響網(wǎng)站的可用性,因?yàn)樵跀?shù)據(jù)庫(kù)備份過程中又與數(shù)據(jù)庫(kù)長(zhǎng)時(shí)間被鎖定而無法寫入任何數(shù)據(jù)
lvm的快照功能可以很好地解決這個(gè)問題,在對(duì)一個(gè)lv創(chuàng)建snapshot時(shí),僅會(huì)復(fù)制其中的元數(shù)據(jù),而不回有任何真實(shí)數(shù)據(jù)的復(fù)制,所以創(chuàng)建過程幾乎是實(shí)時(shí)的。
當(dāng)原有的LV有寫操作時(shí),數(shù)據(jù)會(huì)寫到快照中而不是原LV中(cow),從而保證了原LV中數(shù)據(jù)的一致性。為了確保數(shù)據(jù)一致性,在對(duì)其做快照之前也需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行鎖定操作,
做完快照后再解除鎖。又與快照的過程極為迅速,所以短時(shí)間的數(shù)據(jù)庫(kù)鎖定并不會(huì)對(duì)前臺(tái)應(yīng)用造成影響。
注意:快照創(chuàng)建的大小必須考慮備份期間數(shù)據(jù)的變化量,如果數(shù)據(jù)變化量大于快照的大小則會(huì)造成快照損壞,所以在對(duì)特別重要的數(shù)據(jù)進(jìn)行快照備份時(shí),要讓快照的大小必須至少等于原LV的大小
使用lvm的快照的前提是,mysql數(shù)據(jù)庫(kù)的數(shù)據(jù)文件必須存儲(chǔ)在LV上,數(shù)據(jù)目錄使用邏輯卷。
創(chuàng)建PV
pvcreate mysql_pv /dev/sdb
創(chuàng)建VG
vgcreate mysql_vg /dev/sdb
創(chuàng)建LV
lvcreate -L 1024M -n mysql_lv mysql_vg
格式話掛載
mkfs.ext4 /dev/mysql_vg/mysql_lv
掛載lv
mount /dev/mysql_vg/mysql_lv /mount
關(guān)閉mysql服務(wù),將/var/lib/mysql/中的數(shù)據(jù)全部復(fù)制到新創(chuàng)建的LV中
systemctl stop mysqld
cp -a /var/lib/mysql/* /mnt
將/dev/mysql_vg/mysql_lv重新mount,并啟動(dòng)mysql
umount /dev/mysql_vg/mysql_lv
mount /dev/mysql_vg/mysql_lv /var/lib/mysql/
systemctl start mysqld
最后不要忘記寫/etc/fatab文件,開機(jī)自動(dòng)掛載該LV到/var/lib/mysql/
在對(duì)mysql_lv做快照之前,先使用flush tables和flush tables eith read lock強(qiáng)行將所有OS的緩沖數(shù)據(jù)寫入磁盤(類似于操作系統(tǒng)的sync),同時(shí)將數(shù)據(jù)庫(kù)設(shè)置為全局只讀。
快照完成之后,再使用unlock tables解鎖。然后只需要將快照進(jìn)行掛載,復(fù)制其中的數(shù)據(jù),在復(fù)制完成后刪除該快照即可。
轉(zhuǎn)載于:https://www.cnblogs.com/liangjiongyao/p/10318092.html
總結(jié)
以上是生活随笔為你收集整理的shell在linux里摇摇晃晃的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常见的数据类型
- 下一篇: ONTAK2010 Peaks加强版(离