initial
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
---
|
||||
title: 1.1 linux常用命令与技巧(1)
|
||||
date: 2018-5-3 00:52:22
|
||||
tags: linux
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
### md5sum与sha1sum
|
||||
用于使用hash算法生成文件的摘要信息 , 常用于文件完整性的校验
|
||||
<!-- more -->
|
||||
```bash
|
||||
# 生成a.txt的md5摘要信息
|
||||
md5sum a.txt
|
||||
|
||||
# 生成当前目录下所有文件的sha1摘要信息
|
||||
sha1sum ./*
|
||||
```
|
||||
|
||||
### history
|
||||
显示在终端中执行过的所有命令的历史记录
|
||||
(按↑方向键快速找到执行过的命令也是利用的这个记录)
|
||||
如果使用`history -c`可以清空这个列表
|
||||
|
||||
### chown
|
||||
这个命令是用来改变文件拥有者和所在的组
|
||||
```
|
||||
chown <用户名>:<组> <文件名>
|
||||
```
|
||||
可以改变文件的所有权
|
||||
|
||||
### cal
|
||||
就是calendar(日历) , 可以用来显示当前月份或者任意年份中的某一月
|
||||
```
|
||||
# 显示当前月份日历
|
||||
cal
|
||||
|
||||
# 显示2018年2月的日历
|
||||
cal 2 2018
|
||||
|
||||
# 显示2018年全年日历
|
||||
cal -y 2018
|
||||
```
|
||||
|
||||
### cat
|
||||
代表了连结 , 通常也可以用它输出单个文件的内容
|
||||
```bash
|
||||
# 输出a.txt的内容(带行号)
|
||||
cat -n a.txt
|
||||
|
||||
# 将a.txt b.txt的内容连结输出
|
||||
cat a.txt b.txt
|
||||
```
|
||||
|
||||
### 输出重定向
|
||||
对于程序的输出 , 我们通常不能一直看着终端 , 而且终端也只能保留最近的内容
|
||||
除了程序本身可以有对于日志的处理之外
|
||||
我们也可以将程序向终端的输出重定向到指定的文件里面
|
||||
使用`>`和`>>`可以实现重定向
|
||||
前者表示始终覆盖目标文件 , 后者表示如果目标文件存在则执行追加操作 , 不会覆盖
|
||||
```bash
|
||||
# 执行java程序并将输出写入到当前目录的output.txt文件当中
|
||||
java -jar demo.jar > ./output.txt
|
||||
```
|
||||
当然有些程序会在终端打印大量无意义的内容
|
||||
我们如果想把这些输出直接丢弃
|
||||
可以使用`/dev/null`作为目标位置
|
||||
这是个并不存在的虚拟位置 , 定向到这里相当于是把输出内容直接丢弃 , 避免占用磁盘空间
|
||||
```bash
|
||||
command > /dev/null 2>&1
|
||||
# 1表示标准输出 2表示标准错误输出
|
||||
# 2>&1表示将标准错误输出重定向到标准输出, 这样两者都会被丢弃
|
||||
```
|
||||
|
||||
#### 与cat的配合使用
|
||||
cat既然表示连结 , 那么与输出重定向配合使用 , 就可以实现对于压缩分卷的结合了
|
||||
```bash
|
||||
# 注意分卷的顺序
|
||||
cat data.z01 data.z02 data.zip > xdata.zip
|
||||
# 将分卷结合成一个文件之后就可以执行解压了
|
||||
unzip xdata.zip
|
||||
```
|
||||
|
||||
### grep
|
||||
全称是Global Regular Expression Print, 全局正则表达式输出
|
||||
这个命令的作用是执行全文检索
|
||||
```
|
||||
# 在a.txt当中搜索str1字符串
|
||||
grep "str1" a.txt
|
||||
|
||||
# 在当前目录下递归检索所有文件搜索str1字符串
|
||||
grep -r "str1" ./
|
||||
```
|
||||
当然不限于固定的字符串, 也可以使用正则表达式
|
||||
|
||||
#### 管道符"|"
|
||||
格式 : 命令A|命令B
|
||||
作用是将命令A的输出结果作为命令B的操作对象
|
||||
比如结合`grep`可以对繁杂的输出结果进行过滤
|
||||
```bash
|
||||
# 查询当前运行的进程, 并过滤包含tomcat关键字的行
|
||||
ps ax | grep tomcat
|
||||
```
|
||||
比如`wc -l`可以用来统计行数
|
||||
```
|
||||
# 统计当前目录下总共有多少文件
|
||||
ls -l | wc -l
|
||||
```
|
||||
因为`ls -l`的输出是逐行输出当前目录下每个文件的详细信息 , 所以统计出的行数实际上就是文件数量了
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: 2.0 shell编程(1)-初见
|
||||
date: 2018-5-5 22:38:32
|
||||
tags:
|
||||
- linux
|
||||
- shell
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
`shell`俗称为**壳** , 是指提供使用者使用界面的软件
|
||||
也叫做命令解析器
|
||||
接收用户的命令 , 然后调用相应的应用程序
|
||||
(接收命令的方式可以是命令行 , 也可以是图形界面)
|
||||
<!-- more -->
|
||||
在linux发展过程中 , 出现过很多的shell
|
||||
+ `sh`(全称 Bourne Shell): 是UNIX最初使用的 shell,而且在每种 UNIX 上都可以使用。
|
||||
Bourne Shell 在 shell 编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种 shell。
|
||||
+ `bash`(全称 Bourne Again Shell): LinuxOS 默认的,它是 Bourne Shell 的扩展。
|
||||
与 Bourne Shell 完全兼容,并且在 Bourne Shell 的基础上增加了很多特性。可以提供命令补全,命令编辑和命令历史等功能。它还包含了很多 C Shell 和 Korn Shell 中的优点,有灵活和强大的编辑接口,同时又很友好的用户界面。
|
||||
+ `csh`(全称 C Shell): 是一种比 Bourne Shell更适合的变种 Shell,它的语法与 C 语言很相似。
|
||||
Tcsh: 是 Linux 提供的 C Shell 的一个扩展版本。
|
||||
Tcsh 包括命令行编辑,可编程单词补全,拼写校正,历史命令替换,作业控制和类似 C 语言的语法,他不仅和 Bash Shell 提示符兼容,而且还提供比 Bash Shell 更多的提示符参数。
|
||||
+ `ksh` (全称 Korn Shell): 集合了 C Shell 和 Bourne Shell 的优点并且和 Bourne Shell 完全兼容。
|
||||
+ `pdksh`: 是 Linux 系统提供的 ksh 的扩展。
|
||||
+ `pdksh` 支持人物控制,可以在命令行上挂起,后台执行,唤醒或终止程序。
|
||||
|
||||
---
|
||||
+ **交互式shell** : 等待用户的命令 , 提交后就立即执行该命令
|
||||
+ **非交互式shell** : 不等待用户的输入 , 而是去读取写在文件中的命令代码 , 并且执行 , 这个文件就被称为shell脚本
|
||||
|
||||
> **脚本**其实就是短小的、用来让计算机自动化完成一系列工作的程序,这类程序可以用文本编辑器修改,不需要编译,通常是解释运行的。
|
||||
|
||||
### Hello World
|
||||
test.sh
|
||||
```bash
|
||||
#!/bin/bash
|
||||
echo "Hello World!"
|
||||
```
|
||||
echo就是对传入的参数直接进行输出的程序
|
||||
这个脚本的作用就是执行该命令
|
||||
`#!`是一个约定的标记 , 它告诉系统这个脚本要用什么解释器来执行
|
||||
|
||||
之后需要给这个文件加上可执行权限
|
||||
`chmod +x test.sh`
|
||||
然后就可以执行该脚本了
|
||||
`./test.sh`
|
||||
|
||||
当然如果这样执行 , 是根据脚本内容中指定的解释器运行
|
||||
如果没有指定 , 则使用系统默认的
|
||||
我们也可以在运行时指定使用某个解释器
|
||||
比如`sh test.sh`
|
||||
|
||||
### 变量
|
||||
命名规则是可以包含 字母 数字 下划线 , 且以字母或者数字开头
|
||||
使用变量则是在前面加`$`或者用`${}`
|
||||
( 当然如果在字符串内部使用 , 为了防止歧义, 必须用${} )
|
||||
```bash
|
||||
name="sookie"
|
||||
echo $name
|
||||
echo "my name is ${name}123"
|
||||
# 大括号是为了帮助解释器识别变量名称的边界
|
||||
|
||||
#将该变量设为只读, 之后若再赋值就会报错
|
||||
readonly name
|
||||
```
|
||||
**注意** : 等号的两端不能加空格
|
||||
|
||||
#### 删除变量
|
||||
使用`unset 变量名称`可以删除对应的变量
|
||||
|
||||
> 按照上面方式定义的变量实际上是这个shell脚本当中的**局部变量**
|
||||
在操作系统当中可以设置**环境变量** , 所有的shell脚本当中都可以直接使用
|
||||
|
||||
### 字符串
|
||||
字符串的边界可以是单引号也可以是双引号 也可以无引号 , 但是实际应用当中有一些区别
|
||||
+ `单引号`当中的内容都会原样输出 , 不可以使用转义字符 , 不可以使用字符串模板
|
||||
+ `双引号`当中的内容可以使用转义字符 , 也可以使用字符串模板
|
||||
+ `无引号`不可以使用转义字符 , 但是可以使用字符串模板
|
||||
```bash
|
||||
name="sookie"
|
||||
echo 'my name is ${name}1'
|
||||
# output: my name is ${name}1
|
||||
echo "my name is ${name}1"
|
||||
# output: my name is sookie1
|
||||
echo my name is ${name}1
|
||||
# output: my name is sookie1
|
||||
```
|
||||
#### 字符串操作
|
||||
shell当中字符串的拼接不需要用加号
|
||||
直接写在一起即可
|
||||
```bash
|
||||
name="sookie"
|
||||
echo 'my name is '${name}
|
||||
|
||||
#获取字符串长度
|
||||
echo ${#name}
|
||||
|
||||
#截取子串
|
||||
echo ${name:1:3} #输出 ook
|
||||
|
||||
#将字符串内容当做命令执行
|
||||
echo `ls /usr/local`
|
||||
```
|
||||
|
||||
### 数组
|
||||
同大多数解释型语言一样 , 对于数组并没有严格的越界限制
|
||||
```bash
|
||||
#数组定义, 元素之间用空白分割
|
||||
arr=(1 "aa" 2.6)
|
||||
|
||||
#超出当前数组边界的下标形式赋值, 会将元素追加至末尾
|
||||
arr[6]="bb" #当前数组当中有4个元素
|
||||
|
||||
#获取数组长度
|
||||
echo ${#arr[@]}
|
||||
|
||||
#遍历数组
|
||||
for item in ${arr[@]}
|
||||
do
|
||||
echo ${item}
|
||||
done
|
||||
|
||||
#删除数组元素
|
||||
unset arr[1]
|
||||
```
|
||||
@@ -0,0 +1,219 @@
|
||||
---
|
||||
title: 2.1 shell编程(2)-从入门到重新入门
|
||||
date: 2018-5-5 00:52:22
|
||||
tags:
|
||||
- linux
|
||||
- shell
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
### 传参
|
||||
在外部执行时可以给脚本传参
|
||||
在脚本当中获取时 , `$0`是执行的文件路径
|
||||
`$1`代表第一个参数 , `$2`代表第二个参数 , 以此类推
|
||||
<!-- more -->
|
||||
```bash
|
||||
echo "当前文件:$0"
|
||||
echo "第一个参数:$1"
|
||||
#参数个数
|
||||
echo "共传入$#个参数"
|
||||
|
||||
#遍历所有的参数
|
||||
for arg in $@
|
||||
do
|
||||
echo $arg
|
||||
done
|
||||
|
||||
#脚本运行进程的ID
|
||||
echo "PID:$$"
|
||||
```
|
||||
执行脚本
|
||||
```bash
|
||||
./test.sh aa bb
|
||||
|
||||
#如果参数内容包含空白, 要加引号才能作为一个参数传递
|
||||
./test.sh aa "bb cc"
|
||||
```
|
||||
#### 变量的判断
|
||||
对于shell脚本来说 , 传参通常是比较灵活的
|
||||
所以经常需要判断是否传入了这个参数
|
||||
```bash
|
||||
if [ -n "$1" ]
|
||||
then
|
||||
echo "包含第一个参数"
|
||||
else
|
||||
echo "未包含第一个参数"
|
||||
fi
|
||||
```
|
||||
这是判断某个变量是否有值的方式
|
||||
因为解释型语言的语法比较松散 , 对于变量先定义后使用没有严格要求
|
||||
所以直接使用一个变量而不进行检查可能造成灾难性的后果
|
||||
|
||||
### 运算
|
||||
原生bash对数学运算的支持比较有限
|
||||
##### 方法1 `$((expression))`
|
||||
```bash
|
||||
num1=3
|
||||
num2=4
|
||||
echo $((num1+num2))
|
||||
echo $((num1**num2)) #乘方
|
||||
```
|
||||
变量的引用加不加$都可以 , 不能计算浮点数
|
||||
##### 方法2 `$[expression]`
|
||||
```bash
|
||||
num1=3
|
||||
num2=4
|
||||
echo $[num1+num2]
|
||||
```
|
||||
变量的引用加不加$都可以 , 不能计算浮点数
|
||||
##### 方法3 `let`关键字
|
||||
```bash
|
||||
num1=3
|
||||
num2=4
|
||||
let sum=$num1+$num2
|
||||
echo $sum
|
||||
```
|
||||
变量的引用加不加$都可以 , 不能计算浮点数 , 加号两端不能有空格
|
||||
|
||||
##### 方法4 使用`expr`
|
||||
这是一个内建的用于数学运算的命令
|
||||
需要注意的是运算符两边必须要有空格
|
||||
```bash
|
||||
expr 2 + 6
|
||||
expr 4 - 9
|
||||
#注意为了防止歧义 乘法要写 \* 而不能直接写 *
|
||||
expr 5 \* 4
|
||||
#除法保留整数
|
||||
expr 9 / 2
|
||||
#取余
|
||||
expr 9 % 2
|
||||
|
||||
#浮点数计算
|
||||
expr "3.9 + 1.8"|bc
|
||||
#scale表示保留到的小数位数
|
||||
expr "scale=3;1.2 * 8.73"|bc
|
||||
```
|
||||
|
||||
#### 关系运算
|
||||
bash当中原生支持关系运算
|
||||
|
||||
比较是否相等
|
||||
```bash
|
||||
if [ $a == $b ]
|
||||
then
|
||||
echo "相等"
|
||||
fi
|
||||
|
||||
if [ $a != $b ]
|
||||
then
|
||||
echo "不相等"
|
||||
fi
|
||||
```
|
||||
|
||||
|运算符|含义|其他表示方式|备注|
|
||||
|-----|---|---------|
|
||||
|-eq|是否相等|==|
|
||||
|-ne|是否不相等|!=|
|
||||
|-gt|大于|>|
|
||||
|-lt|小于|<|
|
||||
|-ge|大于等于|\>=|使用\>=需要使用(( ))|
|
||||
|-le|小于等于|<=|使用<=需要使用(( ))|
|
||||
```bash
|
||||
if [ $a -ge $b ]
|
||||
then
|
||||
echo "大于等于"
|
||||
fi
|
||||
# 等价于上面的写法, 注意用(( ))
|
||||
if (( $a >= $b ))
|
||||
then
|
||||
echo "大于等于"
|
||||
fi
|
||||
```
|
||||
> 关系运算符只能用于整数 , 或者能够解析为整数的字符串
|
||||
|
||||
#### 布尔运算
|
||||
|运算符|含义|其他表示方式|
|
||||
|-----|----|---------|
|
||||
|!|非||
|
||||
|-o|或|\|\||
|
||||
|-a|与|&&|
|
||||
```bash
|
||||
# a小于10 并且 b大于20
|
||||
if [ $a -lt 10 -a $b -gt 20 ]
|
||||
then
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
# 与上面的含义相同, 但是注意使用[[ ]]
|
||||
if [[ $a -lt 10 && $b -gt 20 ]]
|
||||
then
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
```
|
||||
> **说明**
|
||||
> 推荐使用 `[[ ... ]]` 条件判断结构,而不是 `[ ... ]`,能够防止脚本中的许多逻辑错误。比如,&&、|| 操作符能够正常存在于 [[ ]] 条件判断结构中,但是如果出现在 [ ] 结构中的话,会报错。
|
||||
|
||||
#### 字符串运算
|
||||
|运算符|含义|
|
||||
|----|-----|
|
||||
|=|两个字符串是否相同(区别于数字的比较)|
|
||||
|!=|两个字符串是否不相同|
|
||||
|-z|字符串长度为0返回true|
|
||||
|-n|字符串长度不为0返回true|
|
||||
```bash
|
||||
a="123"
|
||||
b="456"
|
||||
if [ $a = $b ]
|
||||
then
|
||||
echo "相同"
|
||||
else
|
||||
echo "不同"
|
||||
fi
|
||||
# 字符串本身也可以用作判断条件
|
||||
if [ ! $a ]
|
||||
then
|
||||
echo "字符串为空"
|
||||
fi
|
||||
```
|
||||
使用`-n`和`-z`的时候需要注意 , 需要在字符串变量引用上加双引号
|
||||
```bash
|
||||
if [ -n "$a"]
|
||||
then
|
||||
echo "OK"
|
||||
fi
|
||||
```
|
||||
如果不加双引号 , 当a为空的时候 , 相当于执行
|
||||
`if [ -n ]` , 这个时候会把里面的**-n**当做一个普通字符串来处理 , 而不是运算符
|
||||
自然每次都会是true , **-z** 同理
|
||||
### 文件测试运算符
|
||||
一个字符串也可以表示一个文件(目录)的路径
|
||||
使用这些方式可以获得这个文件的各种信息
|
||||
|运算符|含义|
|
||||
|------|----|
|
||||
|-b file |检测文件是否是块设备文件,如果是,则返回 true|
|
||||
|-c file |检测文件是否是字符设备文件,如果是,则返回 true|
|
||||
|-d file |检测文件是否是目录,如果是,则返回 true|
|
||||
|-f file |检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true|
|
||||
|-g file |检测文件是否设置了 SGID 位,如果是,则返回 true|
|
||||
|-k file |检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true|
|
||||
|-p file |检测文件是否是有名管道,如果是,则返回 true|
|
||||
|-u file |检测文件是否设置了 SUID 位,如果是,则返回 true|
|
||||
|-r file |检测文件是否可读,如果是,则返回 true|
|
||||
|-w file |检测文件是否可写,如果是,则返回 true|
|
||||
|-x file |检测文件是否可执行,如果是,则返回 true|
|
||||
|-s file |检测文件是否为空(文件大小是否大于0),不为空返回 true|
|
||||
|-e file |检测文件(包括目录)是否存在,如果是,则返回 true|
|
||||
|
||||
```bash
|
||||
filepath=/usr/local/test.txt
|
||||
if [ -e filepath ]
|
||||
then
|
||||
echo "文件存在"
|
||||
else
|
||||
echo "文件不存在"
|
||||
fi
|
||||
```
|
||||
@@ -0,0 +1,162 @@
|
||||
---
|
||||
title: shell编程(3)-流程控制&函数
|
||||
date: 2018-5-6 00:52:22
|
||||
tags:
|
||||
- linux
|
||||
- shell
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
### 判断
|
||||
```bash
|
||||
if condition1
|
||||
then
|
||||
command1
|
||||
elif condition2
|
||||
then
|
||||
command2
|
||||
else
|
||||
command3
|
||||
fi
|
||||
```
|
||||
如果else没有语句执行
|
||||
则不能留空 , 最好直接不写这个else
|
||||
<!-- more -->
|
||||
举例
|
||||
```bash
|
||||
if [ `ps ax | grep -c "ssh"` -ge 1 ]
|
||||
then
|
||||
echo "RUNNING"
|
||||
fi
|
||||
# grep的-c参数代表对过滤后的行进行计数
|
||||
|
||||
# 也可以使用test命令做判断
|
||||
if test `ps ax | grep -c "ssh"` -ge 1
|
||||
then
|
||||
echo "RUNNING"
|
||||
fi
|
||||
```
|
||||
|
||||
### 循环
|
||||
#### for循环
|
||||
```bash
|
||||
for ((i=1 ; i<=10 ; i++))
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
# 注意使用(()), 里面的变量并不需要加$
|
||||
```
|
||||
`for (( ; ; ))` - 死循环
|
||||
|
||||
##### foreach
|
||||
bash支持对集合进行迭代的foreach类型语法
|
||||
使用`for ... in ...`
|
||||
```bash
|
||||
# seq命令可以生成一个序列
|
||||
for i in `seq 1 10`
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
|
||||
# 这样也是一个序列
|
||||
for i in {1..10}
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
|
||||
# 迭代遍历一个数组
|
||||
arr=("ab" "cd" "ef")
|
||||
for item in ${arr[@]}
|
||||
do
|
||||
echo $item
|
||||
done
|
||||
```
|
||||
如果一个命令返回的是一个集合 , 也可以执行循环迭代
|
||||
```bash
|
||||
for item in `ls /usr/local`
|
||||
do
|
||||
echo $item
|
||||
done
|
||||
```
|
||||
当然如果是找一个目录下的文件 , 也可以不用ls命令
|
||||
for循环自带路径查找功能
|
||||
```bash
|
||||
for item in /usr/local/*
|
||||
do
|
||||
echo $item
|
||||
done
|
||||
# 注意路径不要加引号
|
||||
```
|
||||
|
||||
#### while循环
|
||||
while循环是在判断条件为false的时候结束循环
|
||||
```bash
|
||||
cnt=1
|
||||
while (( $cnt<=5 ))
|
||||
do
|
||||
echo $cnt
|
||||
let "cnt++"
|
||||
done
|
||||
```
|
||||
`while :`或者`while true`表示死循环
|
||||
#### until循环
|
||||
格式与while循环基本一致 , 只不过是当判断条件为true的时候结束循环
|
||||
```bash
|
||||
cnt=1
|
||||
until (( $cnt>=5 ))
|
||||
do
|
||||
echo $cnt
|
||||
let "cnt++"
|
||||
done
|
||||
```
|
||||
|
||||
#### break与continue
|
||||
表示跳出循环以及继续下一次循环 , 与其他语言当中类似
|
||||
|
||||
### 多选择语句
|
||||
类似其他语言当中的switch , bash当中使用case关键字
|
||||
```bash
|
||||
echo "input a number:"
|
||||
# read表示从终端读取用户输入内容
|
||||
read num
|
||||
case $num in
|
||||
1) echo "数字1"
|
||||
;;
|
||||
2) echo "数字2"
|
||||
;;
|
||||
3|4) echo "3或者4"
|
||||
;;
|
||||
ok) echo "字符串ok"
|
||||
;;
|
||||
*) echo "其他内容"
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
### 函数
|
||||
shell当中可以自定义函数
|
||||
```bash
|
||||
function myFunc() {
|
||||
echo "参数 $1,$2,$3"
|
||||
echo "所有参数:"
|
||||
for arg in $@
|
||||
do
|
||||
echo $arg
|
||||
done
|
||||
}
|
||||
myFunc "aa" "bb"
|
||||
```
|
||||
> **说明** :
|
||||
1. 与获取脚本的参数类似 , 使用`$序号`或者`${序号}`来获取
|
||||
但是如果到了10 , 就必须写作`${10}` , 否则会与$1产生歧义
|
||||
2. `function` 关键字也可以省略
|
||||
|
||||
### 文件包含
|
||||
一个shell脚本当中可以引入另一个shell脚本
|
||||
```bash
|
||||
. /home/sookie/test2.sh
|
||||
# 或者
|
||||
source /home/sookie/test2.sh
|
||||
```
|
||||
被引入的文件并不需要可执行权限
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: shell(4)-使用技巧
|
||||
date: 2018-5-6 00:52:25
|
||||
tags:
|
||||
- linux
|
||||
- shell
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
#### 判断上一条命令执行是否成功
|
||||
`$?`变量的值是上一条命令执行的返回值
|
||||
通过判断这个变量的值 , 可以知道上一条命令是否执行成功
|
||||
```bash
|
||||
if [ $? -eq 0 ];then
|
||||
echo "执行成功"
|
||||
else
|
||||
echo "执行失败"
|
||||
fi
|
||||
```
|
||||
<!-- more -->
|
||||
|
||||
#### 逐行读取文件
|
||||
```bash
|
||||
while read LINE
|
||||
do
|
||||
echo $LINE
|
||||
done < test.txt
|
||||
```
|
||||
@@ -0,0 +1,247 @@
|
||||
---
|
||||
title: 3.1 Docker(1)-初见
|
||||
date: 2018-5-8 22:38:32
|
||||
tags:
|
||||
- linux
|
||||
- docker
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
**程序部署运维的痛点**
|
||||
当今软件越发庞大复杂 , 在服务器部署运行一个软件之前通常需要完成:
|
||||
1. 操作系统的设置
|
||||
2. 各种库和组件的安装
|
||||
|
||||
只有他们都正确 , 软件才能正常运行
|
||||
当需要迁移的时候 , 这些事情都要重来一遍
|
||||
并且由于各种原因 , 还可能会产生不一样的问题 , 费时费力
|
||||
<!-- more -->
|
||||
于是就有了独立运行容器的需求 , 从根本上解决这个问题
|
||||
让软件带环境安装
|
||||
给软件一个独立的环境去运行 , 并且这个软件所有的依赖都在这个环境里面
|
||||
|
||||
|
||||
**虚拟机**
|
||||
虚拟机是一种针对上述问题的解决方案 , 在一个操作系统里面构造一个虚拟环境运行另一个操作系统
|
||||
但是通常会有以下缺陷
|
||||
1. 资源占用多
|
||||
虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。
|
||||
|
||||
2. 冗余步骤多
|
||||
虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。
|
||||
|
||||
3. 启动慢
|
||||
启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。
|
||||
|
||||
**Docker**
|
||||
由于虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器
|
||||
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。
|
||||
|
||||
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。
|
||||
|
||||
Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行
|
||||
|
||||
ubuntu系统直接使用apt安装即可
|
||||
```bash
|
||||
apt install docker.io
|
||||
```
|
||||
|
||||
### 镜像(image)
|
||||
docker把程序及其依赖 , 打包在image文件里面 , 称之为镜像文件
|
||||
它可以看做是生成容器的模板 , 一个镜像文件可以生成多个运行容器实例
|
||||
使用`docker image COMMAND`可以实现对镜像的相关操作
|
||||
|
||||
```bash
|
||||
# 查看本机所有的镜像
|
||||
docker image ls
|
||||
|
||||
# 删除指定镜像
|
||||
docker image rm [ImageId]
|
||||
```
|
||||

|
||||
每个镜像都有一个唯一ID , 是一串hash码
|
||||
我们可以根据这个ID来对指定的镜像进行操作
|
||||
当然也不需要必须写完整 , 只要能找到一个唯一的镜像就可以了
|
||||
比如执行`docker image rm 56a`就可以删除掉express-demo这个镜像了
|
||||
当然使用`docker image rm express-demo`也是可以的
|
||||
> docker中的操作大都是这种模式
|
||||
|
||||
### 容器(container)
|
||||
容器就是程序运行的独立虚拟环境了 , 容器由镜像生成
|
||||
( 镜像可以认为是一种存储的结构 , 而容器才是实际运行的实例 )
|
||||
```bash
|
||||
# 查看运行中的容器
|
||||
docker container ls
|
||||
|
||||
# 运行指定的镜像
|
||||
docker container run [ImageId]
|
||||
|
||||
# 运行指定的容器
|
||||
docker container start [ContainerId]
|
||||
|
||||
# 停止指定的镜像
|
||||
docker container stop [ContainerId]
|
||||
|
||||
# 强行终止指定的镜像
|
||||
docker container kill [ContainerId]
|
||||
```
|
||||
使用`run`每次都会生成一个新的容器文件 , 如果要复用指定的容器 , 可以使用`start`
|
||||
|
||||
|
||||
|
||||
### Hello World
|
||||
这是一个官方提供的最简单的镜像 , 可以用来熟悉docker的基本用法
|
||||
```bash
|
||||
# 从官方仓库拉取镜像
|
||||
docker image pull hello-world
|
||||
|
||||
# 运行这个image
|
||||
docker container run hello-world
|
||||
```
|
||||
> `docker container run`命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的`docker image pull`命令并不是必需的步骤
|
||||
|
||||
这个镜像当中的程序就是在控制台输出一段内容 , 是docker的一些基本介绍
|
||||
|
||||
> image文件生成的容器实例, 本身也是一个文件
|
||||
默认情况下即使容器停止运行 , 这个文件也还是在的 , 不会被删除
|
||||
可以使用`docker container ls -all`来查看所有容器文件
|
||||
使用`docker container rm [ContainerId]`来删除指定的容器文件
|
||||
|
||||
### 尝试制作自己的image并运行
|
||||
这里用一个简单的nodejs项目作为例子 , 尝试制作一个自己的image
|
||||
```bash
|
||||
mkdir express-demo
|
||||
cd express-demo
|
||||
npm init
|
||||
npm install express --save
|
||||
```
|
||||
index.js
|
||||
```javascript
|
||||
const express = require("express")
|
||||
|
||||
var port = 7001
|
||||
const app = express()
|
||||
|
||||
app.get("/", function(req, res){
|
||||
res.send("<h1>Hello World</h1>");
|
||||
})
|
||||
|
||||
const server = app.listen(port, function(){
|
||||
var port = server.address().port;
|
||||
console.log("在%s端口执行监听", port)
|
||||
})
|
||||
```
|
||||
|
||||
#### 编写Dockerfile
|
||||
在此之前 , 我们也可以在项目目录里面加一个`.dockerignore`
|
||||
这个文件表示打包image的时候需要排除在外的内容( 很类似.gitignore )
|
||||
比如
|
||||
```
|
||||
.git
|
||||
node_modules
|
||||
```
|
||||
创建Dockerfile文件
|
||||
```
|
||||
FROM node:9.11
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN npm install
|
||||
EXPOSE 7001
|
||||
```
|
||||
+ `FORM node:9.11` 继承自官方的node镜像 , 冒号后面是标签(通常是版本号)
|
||||
+ `COPY . /app` 将当前目录下的所有文件(除了.dockerignore排除的)都拷贝到image文件的app目录下
|
||||
+ `WORKDIR /app` 工作路径为/app
|
||||
+ `RUN npm install` 在打包image的时候需要执行的 ( 所以这个nodejs项目的依赖包会被打包进image当中 )
|
||||
+ `EXPOSE 7001` 运行时暴露出的端口号
|
||||
|
||||
#### 打包与运行
|
||||
打包image
|
||||
```bash
|
||||
docker image build -t express-demo:1.0 .
|
||||
# -t参数是指定该image的名字 , 冒号后面是标签(默认是latest)
|
||||
# . 表示打包当前目录下的文件
|
||||
```
|
||||
运行
|
||||
```
|
||||
docker container run --rm -p 8000:7001 -it express-demo:1.0 /bin/bash
|
||||
```
|
||||
+ `--rm` 容器停止运行时自动删除容器文件
|
||||
+ `-p` 表示端口映射 , 这里是将容器的7001端口映射到本地的8000端口
|
||||
+ `-it` 容器的 Shell 映射到当前的 Shell,然后你在本机窗口输入的命令,就会传入容器
|
||||
+ **express-demo:1.0** image的名称和标签(当然直接用image的id也可以)
|
||||
+ **/bin/bash** 容器启动后第一个执行的命令 , 这里启动bash , 保证可以使用shell
|
||||
|
||||
执行之后会进入到命令提示符`root@2604657cb46c:/app#`
|
||||
在这里我们就可以执行**node index.js**来运行程序了
|
||||
|
||||
运行之后在外部当然是要通过8000端口来访问
|
||||
|
||||
#### 自动化运行
|
||||
上面的方式在启动容器之后还要手动运行程序 , 还是显得有些繁琐了
|
||||
我们可以在Dockerfile里面加一个CMD的选项
|
||||
```
|
||||
FROM node:9.11
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN npm install
|
||||
EXPOSE 7001
|
||||
CMD node index.js
|
||||
```
|
||||
区别于RUN , CMD是在容器启动的时候执行的 , 而RUN是在打包image的时候执行的
|
||||
|
||||
> 当然 , 有了这个入口 , 就可以自由发挥了
|
||||
比如程序启动比较繁琐 , 完全可以在image里面编写一个shell脚本
|
||||
然后容器启动的时候运行这个脚本即可
|
||||
|
||||
|
||||
#### 其他常用命令
|
||||
查看指定容器的输出 , 即容器里面Shell的标准输出
|
||||
```bash
|
||||
docker container logs [ContainerId]
|
||||
```
|
||||
|
||||
进入一个正在运行的容器
|
||||
```bash
|
||||
docker container exec -it [ContainerID] /bin/bash
|
||||
```
|
||||
之后就可以在容器的shell当中执行命令了
|
||||
|
||||
有时候我们需要把容器当中运行产生的文件拷贝出来
|
||||
可以使用
|
||||
```
|
||||
docker container cp [ContainerId]:[/app/run.log] /home/sookie
|
||||
```
|
||||
上面的命令表示将指定容器的/app/run.log文件拷贝到本地的/home/sookie目录下
|
||||
|
||||
#### 使用国内镜像仓库
|
||||
出于众所周知的原因 , 官方仓库的速度比较慢
|
||||
所以可以把官方镜像的下载地址改为国内的镜像仓库
|
||||
|
||||
|
||||
Docker 官方中国区
|
||||
https://registry.docker-cn.com
|
||||
网易
|
||||
http://hub-mirror.c.163.com
|
||||
ustc
|
||||
https://docker.mirrors.ustc.edu.cn
|
||||
|
||||
##### 方法1 registry-mirror参数
|
||||
直接设置 –registry-mirror 参数,仅对当前的命令有效
|
||||
```bash
|
||||
docker run hello-world --registry-mirror=https://docker.mirrors.ustc.edu.cn
|
||||
```
|
||||
|
||||
##### 方法2 修改/etc/default/docker
|
||||
加入 DOCKER_OPTS=”镜像地址”,可以有多个
|
||||
```
|
||||
DOCKER_OPTS="--registry-mirror=https://docker.mirrors.ustc.edu.cn"
|
||||
```
|
||||
|
||||
##### 方法3 修改/etc/docker/daemon.json
|
||||
```json
|
||||
{
|
||||
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
|
||||
}
|
||||
```
|
||||
> 新版的docker比较推荐方法3
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: 3.2 Docler(2)-使用技巧
|
||||
date: 2018-5-9 22:38:32
|
||||
tags:
|
||||
- linux
|
||||
- docker
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
|
||||
### 与宿主机共享网络
|
||||
默认情况下 , 在宿主机可以根据容器暴露出的端口来访问容器中启动的服务
|
||||
但是由于容器的隔离 , 在容器内部是无法访问宿主机的服务的
|
||||
如果有这种需要 , 可以在启动容器的时候添加参数`--net=host`
|
||||
|
||||
作用就是使容器和宿主机共用网络
|
||||
<!-- more -->
|
||||
### 镜像的备份与恢复
|
||||
docker的一个重要目标就是方便实现迁移
|
||||
对于一个镜像 , 也可以打包出来作为备份 , 或者迁移到其他机器上
|
||||
|
||||
对于镜像的导出与导入操作 , 使用的是`save`和`load`
|
||||
```bash
|
||||
# 备份
|
||||
docker save -o dump.tar [ImageId]
|
||||
|
||||
# 恢复
|
||||
docker load < dump.tar
|
||||
```
|
||||
> 继承的镜像也会一同打包进去
|
||||
再次导入之后 , 该镜像就不再作为一个子镜像存在了
|
||||
比如该镜像继承jre镜像 , 那么打包之后的tar包当中直接包含jre镜像的内容
|
||||
|
||||
### 容器的导出与导入
|
||||
要将一个容器进行导出与导入 , 使用的是`export`和`import`
|
||||
```bash
|
||||
# 导出容器
|
||||
docker export [ContainerId] > demo.tar
|
||||
|
||||
# 导入容器
|
||||
docker import demo.tar [ImageName][:Tag]
|
||||
```
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
title: 3.3 Docker(3)-部署wordpress实践
|
||||
date: 2018-5-10 22:38:32
|
||||
tags:
|
||||
- linux
|
||||
- docker
|
||||
categories:
|
||||
- linux
|
||||
---
|
||||
站在 Docker 的角度,软件就是容器的组合:业务逻辑容器、数据库容器、储存容器、队列容器......Docker 使得软件可以拆分成若干个标准化容器,然后像搭积木一样组合起来。
|
||||
|
||||
这正是微服务(microservices)的思想:软件把任务外包出去,让各种外部服务完成这些任务,软件本身只是底层服务的调度中心和组装层。
|
||||
<!-- more -->
|
||||

|
||||
|
||||
微服务很适合用 Docker 容器实现,每个容器承载一个服务。一台计算机同时运行多个容器,从而就能很轻松地模拟出复杂的微服务架构。
|
||||
|
||||

|
||||
|
||||
|
||||
现在尝试实践搭建一个wordpress的服务
|
||||
这是一个php编写的博客系统
|
||||
|
||||
运行需要依赖的环境有 : mysql php apache
|
||||
当然也包括php的扩展包mysqli , 用于实现mysql数据库的连接
|
||||
|
||||
### 自建wordpress容器
|
||||
|
||||
#### 尝试启动一个php-apache容器
|
||||
创建应用目录 php-demo , 然后进入该目录执行
|
||||
```bash
|
||||
docker container run \
|
||||
-d \
|
||||
--rm \
|
||||
--name wordpress \
|
||||
--volume "$PWD/":/var/www/html \
|
||||
php:7.2-apache
|
||||
```
|
||||
> linux当中 , 命令末尾的`\`代表换行继续输入命令 , 而不立即执行
|
||||
|
||||
+ `-d` : 容器在后台运行 , 输出内容不会打印到终端(可以用docker logs [ContainerId]查看)
|
||||
+ `--rm` : 容器运行停止后 , 自动删除容器文件
|
||||
+ `--name` : 指定容器的名字
|
||||
+ `--volume` : 指定目录映射 , 这里表示把当前目录映射到容器内的/var/www/html目录
|
||||
这个目录是apache服务器对外访问的默认目录
|
||||
这样我们就可以直接在当前目录中添加php页面文件进行访问
|
||||
|
||||
成功从远程仓库下载**php:7.2-apache**镜像并启动容器之后
|
||||
会提示容器对外访问的IP地址 , 比如**172.17.0.2** , 可以直接访问这个地址
|
||||
|
||||
但是此时还没有在访问目录中添加php页面
|
||||
可以写个测试页面index.php
|
||||
```php
|
||||
<?php
|
||||
phpinfo();
|
||||
?>
|
||||
```
|
||||
此时再访问就可以看到php信息了
|
||||
|
||||
#### 安装wordpress
|
||||
删掉index.php
|
||||
官网下载wordpress安装包 , 直接解压到该目录下
|
||||
然后访问就可以看到wordpress的初始化页面了
|
||||

|
||||
但是目前还没有mysql的容器
|
||||
|
||||
#### 运行mysql容器
|
||||
```bash
|
||||
docker container run \
|
||||
-d \
|
||||
--rm \
|
||||
--name wordpressdb \
|
||||
--env MYSQL_ROOT_PASSWORD=123456 \
|
||||
--env MYSQL_DATABASE=wordpress \
|
||||
mysql:5.7
|
||||
```
|
||||
`env`代表向容器中传入的环境变量 , 容器中的mysql会根据环境变量创建数据库以及设置root用户的密码
|
||||
|
||||
#### 添加mysqli扩展
|
||||
PHP 的官方 image 不带有 mysqli 扩展,必须自己新建一个image
|
||||
|
||||
新建`Dockerfile`文件
|
||||
```
|
||||
FROM php:7.2-apache
|
||||
RUN docker-php-ext-install mysqli
|
||||
CMD apache2-foreground
|
||||
```
|
||||
打包镜像时安装mysqli的扩展 , 运行容器时启动apache
|
||||
之后构建image
|
||||
```bash
|
||||
docker build -t php-with-mysql .
|
||||
```
|
||||
|
||||
#### 运行php-with-mysql
|
||||
```bash
|
||||
docker container run \
|
||||
-d \
|
||||
--rm \
|
||||
--volume "$PWD/":/var/www/html \
|
||||
--link wordpressdb:mysqlhost \
|
||||
php-with-mysql
|
||||
```
|
||||
link是实现容器之间通信的一种机制 , 表示该容器要链接到**wordpressdb**容器 , 冒号表示该容器主机的名称是**mysqlhost**
|
||||
(之后配置数据库连接时 , 主机名称不是localhost , 而是**mysqlhost**)
|
||||
|
||||
由于wordpress在运行时需要写入配置文件( 也包括自身版本的更新 )
|
||||
我们可以给当前目录添加写权限
|
||||
```bash
|
||||
chmod -R 777 ./
|
||||
```
|
||||
|
||||
之后再访问172.17.0.2 , 填写数据库配置信息即可完成
|
||||
|
||||
### 使用wordpress官方镜像
|
||||
首先仍然是要启动mysql的容器 , 参考上面的**运行mysql容器**
|
||||
然后使用wordpress的官方镜像构建容器
|
||||
```bash
|
||||
docker container run \
|
||||
-d \
|
||||
--rm \
|
||||
--name wordpress \
|
||||
--env WORDPRESS_DB_PASSWORD=123456 \
|
||||
--link wordpressdb:mysqlhost \
|
||||
wordpress
|
||||
```
|
||||
环境变量`WORDPRESS_DB_PASSWORD`是 MySQL 容器的根密码
|
||||
运行之后的访问和初始化操作和前一种方式相同
|
||||
@@ -0,0 +1 @@
|
||||
个人介绍页面
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Reference in New Issue
Block a user