变量的定义和使用
编写 shell 脚本, 第一行是 #!/bin/bash 代表是个 shell 脚本
输入参数:
形式 | 说明 |
---|---|
$0 | 当前程序的名称 |
$n | 程序的输入参数 n=1 第一个参数 n2 第二个参数 1..n |
$* | 所有输入的参数 |
$# | 输入参数的个数 |
$? | 命令执行的状态,一般返回 0 代表成功 |
先来一个简单的输出 shell
- #!/bin/bash
- echo "haha"
- A=10
- # 代表输出自己
- echo $0
- # 代表输出第一个参数
- echo $1
- # 代表输出第二个参数
- echo $2
- #$? 表示执行是否成功 0 代表成功 非 0 代表失败
- echo "this \$? is $?"
- #$* 列出所有传入的参数
- echo "this \*? is $*"
- #$# 代表输入了几个参数
- echo "this \#? is $#"
执行 ./demo.sh haha hehe 之后输出如下
- [root@cdh-master test]# ./demo.sh haha hehe
- haha
- ./demo.sh
- haha
- hehe
- this $? is 0
- this \*? is haha hehe
- this \#? is 2
循环
for 循环:
- #!/bin/bash
- for i in `seq 1 15`
- do
- echo "数字 $i"
- done
seq 代表取值, 上面代码就是取 1-15 的值
for 循环中的逻辑放在 do 和 done 的中间, 运行上面的代码就会输出 1-15 之间的数字.
使用 for 循环求和:
- #!/bin/bash
- j=0
- for((i=0;i<=100;i++))
- do
- j=`expr $i + $j`
- done
- echo $j
使用加号需要用 expr 关键字来修饰
使用 for 循环, 循环压缩文件
- #!/bin/bash
- j=0
- for i in `find /app/bigdata/test -name "*.sh"`
- do
- tar -cvf chs.tgz $i
- done
通过 find 命令找到某个文件夹下的所有. sh 结尾的文件, 然后通过 tar 命令来压缩.
while 循环:
- #!/bin/bash
- i=0
- while((i<100))
- do
- echo "数字 $i"
- i=`expr $i + 1`
- done
也可以使用下面的方式
- #!/bin/bash
- i=0
- while [[ $i -lt 100 ]]
- do
- echo "数字 $i"
- i=`expr $i + 1`
- done
使用 while 读取文件
- #!/bin/bash
- i=0
- while read line
- do
- echo $line
- # 小于号代表读取出来的内容指向哪里
- done</App/bigdata/test/text.txt
条件
if 语句:
if 语句后面不需要{}, 只需要;, 语句的第一样一定要使用 tab 键输入, 不能使用空格. 空格在 shell 中不能随便写, 代表一个特殊的分割符
- #!/bin/bash
- a=300
- b=200
- if (($a<$b));then
- echo "a<b"
- else
- echo "a>b"
- fi
例子: -d 是判断目录是否存在
- #!/bin/bash
- if [[ ! -d /App/bigdata/hello ]];then
- mkdir -p /App/bigdata/hello
- else
- echo "目录已经存在"
- fi
- -------------------
- #!/bin/bash
- dir=/App/bigdata/test/haha.txt
- if [[ ! -d $dir ]];then
- vi $dir
- else
- echo "文件经存在"
- cat $dir
- fi
算数运算
算数运算符
关系运算符
布尔运算符
字符串运算符
文件测试运算符
算数运算符
运算符 | 说明 | 例子 |
---|---|---|
+ | 加法 | `expr $a + $b` |
- | 减法 | `expr $a - $b` |
* | 乘法 | `expr $a * $b` |
/ | 除法 | `expr $a / $b` |
% | 取余 | `expr $a % $b` |
= | 赋值 | a=$b |
== | 相等 | [ $a==$b ] |
!= | 不相等 | [ $a!=$b ] |
注意: 条件表达式要放在中括号内, 并且要有空格!
算数运算符中我们不能直接使用运算符得到结果比如 1+1, 只会输出一个字符串 "1+1", 想要得到结果有四种方式, 建议使用第四种
- $(( 4 + 5 ))
- $[ 4 + 5 ]
- n=10 let n=n+1
命令 | 描述 | 例子 |
---|---|---|
-eq | 等于 | [ $a -eq $b ] |
-ne | 不等于 | [ $a -ne $b ] |
-gt | 大于 | [ $a -gt $b ] |
-lt | 小于 | [ $a -lt $b ] |
-ge | 大于等于 | [ $a -ge $b ] |
-le | 小于等于 | [ $a -le $b ] |
布尔运算符:
命令 | 描述 | 例子 |
---|---|---|
! | 非运算 | [ !false ] |
-a | 与运算 | [ $a -lt 20 -a $b -gt 100 ] |
-o | 或运算 | [$a -lt 20 -o $b -gt 100] |
逻辑运算符
命令 | 描述 | 例子 | ||||
---|---|---|---|---|---|---|
&& | 逻辑中的 and | [[ $a -lt 100 && $b -gt 200]] | ||||
` | ` | 逻辑中的 or | [[ $a -lt 100 ` | ` $b -gt 200]] |
字符串运算符
命令 | 描述 | 例子 |
---|---|---|
= | 两个字符串相等 | [ $a=$b ] |
!= | 两个字符串不等 | [ $a!=$b ] |
-z | 字符串长度是否为 0 0 返回 true | [ -z $a ] |
-n | 字符串长度是否为 0 非 0 返回 true | [ -n “$a” ] |
$ | 字符串是否为空 非空返回 true | [ $a ] |
文件测试运算符
$file 代表文件的路径
命令 | 描述 | 例子 |
---|---|---|
-b | 文件是否是块设备文件 | [ -f $file ] |
-c | 文件是否是字符设备文件 | [ -f $file ] |
-d | 目录是否存在 | [ -d $file ] |
-f | 文件是否存在 | [ -f $file ] |
-g | 文件是否设置了 SGID 位 | [ -f $file ] |
-k | 文件是否设置粘着 (Sticky Bit) 位 | [ -f $file ] |
-p | 文件是否有名管道 | [ -f $file ] |
-u | 文件是否置了 SUID 位 | [ -f $file ] |
-r | 文件是否可读 | [ -f $file ] |
-w | 文件是否可写 | [ -f $file ] |
-x | 文件是否可执行 | [ -f $file ] |
-s | 文件是否为空 | [ -f $file ] |
-e | 文件 (包括目录) 是否存在 | [ -f $file ] |
重定向
Linux 中一切皆文件
描述符:
标准输入 standard input0 (默认设备键盘)
标准输出 standard input1 (默认设备显示器)
错误输出 error input2 (默认设备显示器)
输出重定向> 比如 cat 0<text.txt
输出重定向 < 比如 echo hello> filename
方法函数
定义一个函数
第一种:
name() { }
第二种:
- [ function ] funname [()]
- {
- action;
- [return int;]
- }
例子:
- #!/bin/bash
- aa="this is aa"
- bb="this is bb"
- function test(){
- echo $1
- cc="this. is cc"
- dd="this is dd"
- echo $cc
- echo "我是一个函数"
- }
- # 调用函数并传参
- test 10
- #!/bin/bash
- a=1;
- factorial(){
- # 此处 $1 是西面调用的时候传过来的参数
- for i in `seq $1`
- do
- let a*=$i
- done
- echo "$1 的阶乘 $a"
- }
- # 此处 $1 是外部传入的参数
- factorial $1
函数的返回值
- #!/bin/bash
- fun2(){
- read -p "请输入数值" num
- let 2*num
- }
- fun2
- echo "fun2 return value: $?"
$? 代表取上一条指令的返回值, 上面的函数返回值为 0.0 代表执行成功, 非 0 表执行失败(数值在 0-255 之间)
可以通过 echo 的方法返回一个数值
- #!/bin/bash
- fun2(){
- read -p "请输入数值" num
- echo $[2*$num]
- }
- result=`fun2`
- echo "fun2 return value: $result"
使用 shell 脚本编译 FFMPEG
FFMPEG 是一套可以用来记录, 转换数字音频, 视频, 并能将其转化为流的开源计算机程序.
FFMPEG 是一个多媒体视频处理工具, 具有非常强大的功能, 包括视频采集功能, 视频格式转换, 视频抓图, 给视频添加水印等.
FFMPEG 组成部分
FFMPEG 工具: 1.FFMPEG 2.FFplay 3.FFprobe
FFMPEG 开发库:
- Libavcdec
- Libavutil
- Libavfrmat
- Libavdebice
- Libavfilter
- Libswscale
- Libswresample
FFMPEG 下载地址: http://www.ffmpeg.org/download.html
如果我们编译到 Android 中使用, 需要用到 Android 的 NDK
NDK 下载:
wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
下载完 NDK 配置环境变量
- VIM /etc/profile
- NDKROOT=/App/bigdata/test/Android-ndk-r17c
- export PATH=$NDKROOT:$PATH
- sorce /etc/profile
然后执行 ndk-build 如果打印下面的信息就说明配置 OK
- [root@cdh-master Android-ndk-r17c]# ndk-build
- Android NDK: Could not find application project directory !
- Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
把下载的 FFMPEG 的压缩包上传到服务器
解压 tar -xjf FFMPEG-4.1.3.tar.bz2 报错
- [root@cdh-master test]# tar -xjf FFMPEG-4.1.3.tar.bz2
- tar (child): bzip2: Cannot exec: No such file or directory
- tar (child): Error is not recoverable: exiting now
- tar: Child returned status 2
- tar: Error is not recoverable: exiting now
因为没有安装 bzip2, 给它安装
yum install bzip2
在解压 OK
下面开始编译 FFMPEG, 因为编译的时候需要指定很多参数, 所以把它们写到一个 shell 脚本中方便查看和执行.
进入到 FFMPEG-4.1.3 的解压目录中, 新建一个 build.sh
- #!/bin/bash
- #NDK 的安装目录
- NDK_ROOT=/root/ndk/Android-ndk-r17c
- #TOOLCHAIN 变量指向 ndk 中的交叉编译 gcc 所在的目录
- TOOLCHAIN=$NDK_ROOT/toolchains/ARM-Linux-androideabi-4.9/prebuilt/Linux-x86_64/
- #FLAGS 与 INCLUDES 变量 可以从 AS ndk 工程的. externativeBuild/cmake/debug/armeabi-v7a/build.ninja 中拷贝, 需要注意的是 ** 地址 **
- FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -O0 -fPIC"
- INCLUDES="-isystem $NDK_ROOT/sources/cxx-stl/llvm-libc++/include -isystem $NDK_ROOT/sources/android/support/include -isystem $NDK_ROOT/sources/cxx-stl/llvm-libc++abi/include"
- # 执行 configure 脚本, 用于生成 makefile
- #--prefix : 安装目录
- #--enable-small : 优化大小
- #--disable-programs : 不编译 FFMPEG 程序 (命令行工具), 我们是需要获得静态(动态) 库.
- #--disable-avdevice : 关闭 avdevice 模块, 此模块在 Android 中无用
- #--disable-encoders : 关闭所有编码器 (播放不需要编码)
- #--disable-muxers : 关闭所有复用器(封装器), 不需要生成 mp4 这样的文件, 所以关闭
- #--disable-filters : 关闭视频滤镜
- #--enable-cross-compile : 开启交叉编译(FFMPEG 比较 ** 跨平台 **, 并不是所有库都有这么 happy 的选项 )
- #--cross-prefix: 看右边的值应该就知道是干嘛的, gcc 的前缀 xxx/xxx/xxx-gcc 则给 xxx/xxx/xxx-
- #disable-shared enable-static 不写也可以, 默认就是这样的.
- #--sysroot:
- #--extra-cflags: 会传给 gcc 的参数
- #--arch --target-os :
- PREFIX=./Android/armeabi-v7a2
- ./configure \
- --prefix=$PREFIX \
- --prefix=$PREFIX \
- --enable-small \
- --disable-programs \
- --disable-avdevice \
- --disable-encoders \
- --disable-muxers \
- --disable-filters \
- --enable-cross-compile \
- --cross-prefix=$TOOLCHAIN/bin/ARM-Linux-androideabi- \
- --disable-shared \
- --enable-static \
- --sysroot=$NDK_ROOT/platforms/Android-21/arch-ARM \
- --extra-cflags="$FLAGS $INCLUDES" \
- --extra-cflags="-isysroot $NDK_ROOT/sysroot" \
- --arch=ARM \
- --target-os=Android
- make clean
- make install
保存执行几分钟后, 会看到生成了一个 andorid 目录, 里面就是编译完成的文件.
来源: http://www.tuicool.com/articles/2qQ3Yrv