這篇文章主要通過工作中shell腳本案例,介紹shell腳本中常用知識點
下面的這個腳本表示使用sqoop把生產數據庫mysql中的商戶交易數據導入到hive數據庫,且生產數據庫中商戶交易數據是分庫分表存放的(10個庫100個表中),分表分庫原則根據商戶F_merchant_id來分的,比如說一個商戶號F_merchant_id='xxxxx855',可以看到商戶號是倒數第三位是8,分庫的時候會存放到第8個數據庫中,最後兩位數字是55,所以分表的時候會存放到第55張表中。所以對於商戶號xxxxx855的所有交易數據會存放到第8個數據庫,第55個表中。
#抽取從2019年1月4號到2019年2月10日的所有商戶交易數據
begin_date="20190104" #定義開始時間變量
end_date="20190210" #定義結束時間變量
while [ "$begin_date" -le "$end_date" ] #$begin_date表示參數的引用
do
y=${begin_date:0:4}
m=${begin_date:4:2}
d=${begin_date:6:2}
echo "${y}-${m}"
begin_date=$(date -d "${begin_date}+1days" +%Y%m%d)
y1=${begin_date:0:4}
m1=${begin_date:4:2}
d1=${begin_date:6:2}
for ((db=0;db<=9;db=db+1)) #從0到9,每次加1,共迭代10次 循環10個庫
do
for ((j=0;j<=99;j=j+10))
do
querystr=''
for((k=1;k<=10;k++))#一次union 10個表
do
tb1[$k]=$[(${j}+k-1)/10] #相除
tb2[$k]=$[(${j}+k-1)%10] #取餘
table[$k]="select F_transaction_id,F_order_id,F_merchant_id from datafrog${db}.t_transaction_operation_by_merchant_${tb1[$k]}${tb2[$k]} where F_time>='${y}-${m}-${d}' AND F_time<'${y1}-${m1}-${d1}' "
if [ $k -gt 1 ]
then
querystr="${querystr} union all ${table[$k]} "
else
querystr="${table[$k]}"
fi
done
#下面的腳本大家不需要看,是爲整體效果做的展示
sqoop import \
--connect "jdbc:mysql://192.XXX.XX.XX/datafrog?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&tinyInt1isBit=false" \
--driver com.mysql.jdbc.Driver \
--username datafrog \
--password www.datafrog.com \
--query \
"${querystr}" \
--fields-terminated-by '\t' \
--fetch-size 50000 \
--direct \
--append \
--target-dir /user/hadoop/sqoop/notcm/tran/$y$m$d \
-m 1
done
done
done
1.創建一個shell腳本
linux 系統中打開文本編輯器(可以使用 vi/vim命令來創建文件),新建一個文件 test.sh,擴展名爲sh(sh代表shell)。輸入一些代碼,第一行一般是這樣:
如下:
#!/bin/bash
echo "Hello World !"
2.給shell腳本賦權限
一般寫好的shell腳本要先賦權限然才能後執行
chmod +x ./test.sh #使腳本具有執行權限
./test.sh #執行腳本
3.shell腳本中while循環使用
while 語句格式
while condition
do
command
done
while循環案例
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
運行腳本,輸出:
1
2
3
4
5
使用中使用了 Bash let 命令,它用於執行一個或多個表達式,變量計算中不需要加上$來表示變量
4.shell腳本中for 循環使用
for 循環與其他編程語言類似,Shell支持for循環。for循環一般格式爲:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
例如,順序輸出當前列表中的數字:
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
輸出結果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
5.Shell腳本中字符串的拼接
如果想要在字符串變量後面拼接一個字符,可以用下面的方法:
value1=home
value2=${value1}"=" # 或者$value2=${value1}=
echo $value2
把要添加的字符串變量添加{}中,並且需要把$放到外面,上面的結果是:home=
還可以如下面的
[root@localhost sh]# var1=/etc/
[root@localhost sh]# var2=yum.repos.d/
[root@localhost sh]# var3=${var1}${var2}
[root@localhost sh]# echo $var3
/etc/yum.repos.d/
6.shell腳本中的關係運算符
- -eq:等於 equal
- -ne:不等於 not equal
- -le:小於等於 less equal
- -ge:大於等於 greater equal
- -lt:小於 less than
- -gt:大於 greater than
7.shell腳本中獲取系統時間的方法
獲取今天時期:
$(date +%Y%m%d)
或$(date +%F
或$(date +%y%m%d)
獲取昨天時期:
$(date -d yesterday +%Y%m%d)
獲取前天日期:
$(date -d -2day +%Y%m%d)
獲取10天前的日期:
$(date -d -10day +%Y%m%d)
n天前的
$(date -d "n days ago" +%y%m%d)
明天:
$(date -d tomorrow +%y%m%d)
- 給定的日期減一天
$(date -d "20150416 -1 days" +%Y%m%d)
- 給定的日期減去三天
$(date -d "20150416 -3 days" +%Y%m%d)
- 給定的日期加上三天
date -d "20150416 3 days" "+%Y%m%d"
7.shell腳本中字符串截取
可以使用這樣的方法截取,表示從左邊第幾個字符開始以及字符的個數,用法爲:start:len
例如:
str='http://www.
你的域名.com/cut-string.html'
echo ${str:0:5}
輸出結果
結果是:http:
其中的 0 表示左邊第一個字符開始,5 表示字符的總個數。
8.shell腳本中數組的使用
數組中可以存放多個值。Bash Shell 只支持一維數組(不支持多維數組),初始化時不需要定義數組大小,與大部分編程語言類似,數組元素的下標由0開始。
(1)創建數組
shell數組用括號來表示,元素用"空格"符號分割開,語法格式如下:
array_name=(value1 ... valuen)
實列
#!/bin/bash
my_array=(A B "C" D)
我們也可以使用下標來定義數組:
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
(2)讀取數組
讀取數組元素值的一般格式是:
${array_name[index]}
實例
#!/bin/bash
my_array=(A B "C" D)
echo "第一個元素爲: ${my_array[0]}"
echo "第二個元素爲: ${my_array[1]}"
echo "第三個元素爲: ${my_array[2]}"
echo "第四個元素爲: ${my_array[3]}"
執行腳本,輸出結果如下所示:
$ chmod +x test.sh
$ ./test.sh
第一個元素爲: A
第二個元素爲: B
第三個元素爲: C
第四個元素爲: D
9.shell腳本中重定向
針對於上面提到的sqoop抽取數據的腳本,工作中是使用azkaban做任務調度。但是有時候做其他的定時任務也使用crontab做來任務調度
比如下面的數據蛙課程案例,每天定時發送郵件的定時任務
35 8 * * * /root/anaconda3/bin/python3.6 /root/project/datafrog/datafrog_adventure.py >/tmp/load.log 2>&1 #郵件發送by 數據蛙
這個裏面就涉及到了shell腳本中的重定向,下面一起看看把
我們先來看下linux命令的執行過程
我們一起來看下,比如說一條linux命令
一開始可能需要給這個命令一個輸入值,這個就叫標準輸入(Standard input),簡寫stdin
,其中可以通過鍵盤或者是文件的形式給命令一個輸入接着就開始執行命令,命令執行成功,就會把成功的結果輸出到屏幕上來,這個就叫標準輸出(standard output),簡寫stout
若是命令行執行錯誤,就會把報錯的結果輸出到屏幕上來,這個就叫做標準錯誤(standard error),簡寫stderr
有時候我們在命令使用時,若不想命令的執行結果輸出的屏幕,需要輸入輸出到制定文件或者設備,就需要使用輸入、輸出重定向。
先看下輸出重定向的例子
#默認情況下,stdout和stderr默認輸出到屏幕
[root@st ~]# ls ks.cfg wrongfile
ls: cannot access wrongfile: No such file or directory
ks.cfg
#標準輸出重定向到stdout.txt文件中,錯誤輸出默認到屏幕。1>與>等價
[root@st ~]# ls ks.cfg wrongfile >stdout.txt
ls: cannot access wrongfile: No such file or directory
[root@st ~]# cat stdout.txt
ks.cfg
#標準輸出重定向到stdout.txt,錯誤輸出到err.txt。也可以使用追加>>模式。
[root@st ~]# ls ks.cfg wrongfile >stdout.txt 2>err.txt
[root@st ~]# cat stdout.txt err.txt
ks.cfg
ls: cannot access wrongfile: No such file or directory
#將錯誤輸出關閉,輸出到null。同樣也可以將stdout重定向到null或關閉
# &1代表標準輸出,&2代表標準錯誤,&-代表關閉與它綁定的描述符
[root@st ~]# ls ks.cfg wrongfile 2>&-
ks.cfg
[root@st ~]# ls ks.cfg wrongfile 2>/dev/null
ks.cfg
#將錯誤輸出傳遞給stdout,然後stdout重定向給xx.txt,也可以重定向給null。順序爲stderr的內容先到xx.txt,stdout後到。
[root@st ~]# ls ks.cfg wrongfile >xx.txt 2>&1
#將stdout和stderr重定向到null
[root@st ~]# ls ks.cfg wrongfile &>/dev/null
注意關於2>&1的理解
- 含義:將標準錯誤輸出重定向到標準輸出
- 符號>&是一個整體,不可分開,分開後就不是上述含義了。比如有些人可能會這麼想:2是標準錯誤輸入,1是標準輸出,>是重定向符號,那麼"將標準錯誤輸出重定向到標準輸出"是不是就應該寫成"2>1"就行了?是這樣嗎?如果是嘗試過,你就知道2>1的寫法其實是將標準錯誤輸出重定向到名爲"1"的文件裏去了
- 寫成2&>1也是不可以的
輸入重定向
#從stdin(鍵盤)獲取數據,然後輸出到catfile文件,按Ctrl+d結束
[root@st ~]# cat >catfile
this
is
catfile
[root@st ~]# cat catfile
this
is
catfile
#輸入特定字符eof,自動結束stdin
[root@st ~]# cat >catfile <<eof
> this
> is
> catfile
> eof
[root@st ~]# cat catfile
this
is
catfile
如果大家正在學習shell腳本使用的話,不防好好讀下sqoop抽取數據的腳本,通過實際的案例學習,成長速度會更快些