【Linux】【Shell】【Basic】Programming
shell脚本编程:
编程语言的分类:根据运行方式
编译运行:源代码--》编译器(编译)--》程序文件
解释运行:源代码--》运行时启动解释器,又解释器边解释边运行
根据其编程过程中功能的实现是调用库还是调用外部的程序文件:、
shell脚本编程:
利用系统上的命令及编程组件进行编程;
完整编程:
利用库或编程组件进行编程;
编程模型:过程式编程语言,面向对象的编程语言
程序=指令+数据
过程式:以指令为中心来组织代码,数据是服务于代码;
顺序执行
选择执行
循环执行
代表:C,bash
对象式:以数据为中心来组织代码,围绕数据来组织指令;
类(class):实例化对象,method;
代表:Java, C++, Python
shell脚本编程:过程式编程,解释运行,依赖于外部程序文件运行;
如何写shell脚本:
脚本文件的第一行,顶格:给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件
常见的解释器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
文本编程器:nano
行编辑器:sed
全屏幕编程器:nano, vi, vim
shell脚本是什么?
命令的堆积;
但很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误;
运行脚本:
(1) 赋予执行权限,并直接运行此程序文件;
chmod +x /PATH/TO/SCRIPT_FILE
/PATH/TO/SCRIPT_FILE
(2) 直接运行解释器,将脚本以命令行参数传递给解释器程序;
bash /PATH/TO/SCRIPT_FILE
注意:脚本中的空白行会被解释器忽略;
脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行;
shell脚本的运行是通过运行一个子shell进程实现的;
练习1:写一个脚本,实现如下功能;
(1) 显示/etc目录下所有以大写p或小写p开头的文件或目录本身;
(2) 显示/var目录下的所有文件或目录本身,并将显示结果中的小写字母转换为大写后显示;
(3) 创建临时文件/tmp/myfile.XXXX;
bash的配置文件:
两类:
profile类:为交互式登录的shell进程提供配置
全局:对所有用户都生效;
/etc/profile
/etc/profile.d/*.sh
用户个人:仅对当前用户有效;
~/.bash_profile
功用:
1、用于定义环境变量;
2、运行命令或脚本;
bashrc类:为非交互式登录的shell进程提供配置
全局:
/etc/bashrc
用户个人:
~/.bashrc
功用:
1、定义本地变量;
2、定义命令别名;
注意:仅管理员可修改全局配置文件;
登录类型:
交互式登录shell进程:
直接通过某终端输入账号和密码后登录打开的shell进程;
使用su命令:su - USERNAME, 或者使用 su -l USERNAME执行的登录切换;
/etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录shell进程:
su USERNAME执行的登录切换;
图形界面下打开的终端;
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
运行脚本
命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
配置文件定义的特性,只对随后新启动的shell进程有效;
让通过配置文件定义的特性立即生效:
(1) 通过命令行重复定义一次;
(2) 让shell进程重读配置文件;
~]# source /PATH/FROM/CONF_FILE
~]# . /PATH/FROM/CONF_FILE
bash脚本编程
脚本文件格式:
第一行,顶格:#!/bin/bash
注释信息:#
代码注释:
缩进,适度添加空白行;
语言:编程语法格式,库,算法和数据结构
编程思想:
问题空间 --> 解空间
变量:
局部变量
本地变量
环境变量
位置参数变量
特殊变量
数据类型:字符型、数值型
弱类型:字符型
算术运算:
+, -, *, /, %, **
let VAR=expression
VAR=$[expression]
VAR=$((expression))
VAR=$(expr argu1 argu2 argu3)
注意:有些时候乘法符号需要转义;
增强型赋值:
变量做某种算术运算后回存至此变量中;
let i=$i+#
let i+=#
+=,-=,*=, /=, %=
自增:
VAR=$[$VAR+1]
let VAR+=1
let VAR++
自减:
VAR=$[$VAR-1]
let VAR-=1
let VAR--
练习:
1、写一个脚本
计算/etc/passwd文件中的第10个用户和第20个用户的id号之和;
id1=$(head -10 /etc/passwd | tail -1 | cut -d: -f3)
id2=$(head -20 /etc/passwd | tail -1 | cut -d: -f3)
2、写一个脚本
计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和;
grep "^[[:space:]]*$" /etc/rc.d/init.d/functions | wc -l
条件测试:
判断某需求是否满足,需要由测试机制来实现;
如何编写测试表达式以实现所需的测试:
(1) 执行命令,并利用命令状态返回值来判断;
0:成功
1-255:失败
(2) 测试表达式
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
注意:EXPRESSION两端必须有空白字符,否则为语法错误;
bash的测试类型:
数值测试
字符串测试
文件测试
数值测试:数值比较
-eq:是否等于; [ $num1 -eq $num2 ]
-ne:是否不等于;
-gt:是否大于;
-ge:是否大于等于;
-lt:是否小于;
-le:是否小于等于;
字符串测试:
==:是否等于;
>:是否大于;
<:是否小于;
!=:是否不等于;
=~:左侧字符串是否能够被右侧的PATTERN所匹配;
-z "STRING":判断指定的字串是否为空;空则为真,不空则假;
-n "STRING":判断指定的字符串是否不空;不空则真,空则为假;
注意:
(1) 字符串要加引用;
(2) 要使用[[ ]];
文件测试:
存在性测试
-a FILE
-e FILE
文件的存在性测试,存在则为真,否则则为假;
存在性及类型测试
-b FILE:是否存在并且为 块设备 文件;
-c FILE:是否存在并且为 字符设备 文件;
-d FILE:是否存在并且为 目录文件;
-f FILE:是否存在并且为 普通文件;
-h FILE或 -L FILE:是否存在并且为 符号链接文件;
-p FILE:是否存在且为 命名管道文件;
-S FILE:是否存在且为 套接字文件;
文件权限测试:
-r FILE:是否存在并且 对当前用户可读;
-w FILE:是否存在并且 对当前用户可写;
-x FILE:是否存在并且 对当前用户可执行;
特殊权限测试:
-u FILE:是否存在并且 拥有suid权限;
-g FILE:是否存在并且 拥有sgid权限;
-k FILE:是否存在并且 拥有sticky权限;
文件是否有内容:
-s FILE:是否有内容;
时间戳:
-N FILE:文件自从上一次读操作后是否被修改过;
从属关系测试:
-O FILE:当前用户是否为文件的属主;
-G FILE:当前用户是否属于文件的属组;
双目测试:
FILE1 -ef FILE2:FILE1与FILE2是否指向同一个文件系统的相同inode的硬链接;
FILE1 -nt FILE2:FILE1是否新于FILE2;
FILE1 -ot FILE2:FILE1是否旧于FILE2;
组合测试条件:
逻辑运算:
第一种方式:
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
[ -O FILE ] && [ -r FILE ]
第二种方式:
EXPRESSION1 -a EXPRESSION2
EXPRESSION1 -o EXPRESSION2
! EXPRESSION
[ -O FILE -a -x FILE ]
练习:将当前主机名称保存至hostName变量中;
主机名如果为空,或者为localhost.localdomain,则将其设置为www.magedu.com;
hostName=$(hostname)
[ -z "$hostName" -o "$hostName" == "localhost.localdomain" -o "$hostName" == "localhost" ] && hostname www.magedu.com
脚本的状态返回值:
默认是脚本中执行的最后一条件命令的状态返回值;
自定义状态退出状态码:
exit [n]:n为自己指定的状态码;
注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束;
向脚本传递参数:
位置参数变量
myscript.sh argu1 argu2
引用方式:
$1, $2, ..., ${10}, ${11}, ...
轮替:
shift [n]:位置参数轮替;
练习:写一脚本,通过命令传递两个文本文件路径给脚本,计算其空白行数之和;
#!/bin/bash
#
file1_lines=$(grep "^$" $1 | wc -l)
file2_lines=$(grep "^$" $2 | wc -l)
echo "Total blank lines: $[$file1_lines+$file2_lines]"
特殊变量:
$0:脚本文件路径本身;
$#:脚本参数的个数;
$*:所有参数
$@:所有参数
过程式编程语言的代码执行顺序:
顺序执行:逐条运行;
选择执行:
代码有一个分支:条件满足时才会执行;
两个或以上的分支:只会执行其中一个满足条件的分支;
循环执行:
代码片断(循环体)要执行0、1或多个来回;
选择执行:
单分支的if语句:
if 测试条件
then
代码分支
fi
双分支的if语句:
if 测试条件; then
条件为真时执行的分支
else
条件为假时执行的分支
fi
示例:通过参数传递一个用户名给脚本,此用户不存时,则添加之;
#!/bin/bash
#
if ! grep "^$1\>" /etc/passwd &> /dev/null; then
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
echo "Add user $1 finished."
fi
#!/bin/bash
#
if [ $# -lt 1 ]; then
echo "At least one username."
exit 2
fi
if ! grep "^$1\>" /etc/passwd &> /dev/null; then
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
echo "Add user $1 finished."
fi
#!/bin/bash
#
if [ $# -lt 1 ]; then
echo "At least one username."
exit 2
fi
if grep "^$1\>" /etc/passwd &> /dev/null; then
echo "User $1 exists."
else
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
echo "Add user $1 finished."
fi
练习1:通过命令行参数给定两个数字,输出其中较大的数值;
#!/bin/bash
#
if [ $# -lt 2 ]; then
echo "Two integers."
exit 2
fi
if [ $1 -ge $2 ]; then
echo "Max number: $1."
else
echo "Max number: $2."
fi
#!/bin/bash
#
if [ $# -lt 2 ]; then
echo "Two integers."
exit 2
fi
declare -i max=$1
if [ $1 -lt $2 ]; then
max=$2
fi
echo "Max number: $max."
练习2:通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数;
练习3:通过命令行参数给定两个文本文件名,如果某文件不存在,则结束脚本执行;
都存在时返回每个文件的行数,并说明其中行数较多的文件;
练习:
1、创建一个20G的文件系统,块大小为2048,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/testing目录,且默认有acl挂载选项;
(1) 创建20G分区;
(2) 格式化:
mke2fs -t ext4 -b 2048 -L 'TEST' /dev/DEVICE
(3) 编辑/etc/fstab文件
LABEL='TEST' /testing ext4 defaults,acl 0 0
2、创建一个5G的文件系统,卷标HUGE,要求此分区开机自动挂载至/mogdata目录,文件系统类型为ext3;
3、写一个脚本,完成如下功能:
(1) 列出当前系统识别到的所有磁盘设备;
(2) 如磁盘数量为1,则显示其空间使用信息;
否则,则显示最后一个磁盘上的空间使用信息;
if [ $disks -eq 1 ]; then
fdisk -l /dev/[hs]da
else
fdisk -l $(fdisk -l /dev/[sh]d[a-z] | grep -o "^Disk /dev/[sh]d[a-]" | tail -1 | cut -d' ' -f2)
fi
bash脚本编程之用户交互:
read [option]... [name ...]
-p 'PROMPT'
-t TIMEOUT
bash -n /path/to/some_script
检测脚本中的语法错误
bash -x /path/to/some_script
调试执行
示例:
#!/bin/bash
# Version: 0.0.1
# Author: MageEdu
# Description: read testing
read -p "Enter a disk special file: " diskfile
[ -z "$diskfile" ] && echo "Fool" && exit 1
if fdisk -l | grep "^Disk $diskfile" &> /dev/null; then
fdisk -l $diskfile
else
echo "Wrong disk special file."
exit 2
fi
【Linux】【Shell】【Basic】Programming的更多相关文章
- 【Linux下自定义Shell终端提示符】
目录 基本转义符 字体颜色 背景颜色 移动光标 @ Linux系统终端提示符的特征由系统环境变量 PS1(Prompt String One)定义. 我们可以通过命令echo $PS1来查看当前设置, ...
- 【linux之挂载,Raid,LVM】
一.挂载,卸载 挂载:将新的文件系统关联至当前根文件系统卸载:将某文件系统与当前根文件系统的关联关系移除 cat /etc/mtab 存储着已经挂载的文件系统 (跟 mount 一样) mount:显 ...
- 【Linux&Unix--open/close/write/read系统调用】
个人学习整理.如有不足之处,请不吝不吝赐教. 转载请注明:@CSU-Max 系列博文: Linux&Unix学习第一弹 -- 文件描写叙述符与权限 Linux&Unix学习 ...
- 【linux之设备,分区,文件系统】
一.设备 IDE磁盘的设备文件采用/dev/hdx来命名,分区则采用/dev/hdxy来命名,其中x表示磁盘(a是第一块磁盘,b是第二块磁盘,以此类推), y代表分区的号码(由1开始,..3以此类推) ...
- 【linux之进程管理,系统监控】
一.进程管理 前台进程:一般是指占据着标准输入和/或标准输出的进程后台进程:不占据默认开启的进程都是前台进程ctrl+C 中断ctrl+z 从前台转入后台bg 后台进程编号 让其在后台运行ls -R ...
- 【python中调用shell命令使用PIPE】使用PIPE作为stdout出现假卡死的情况——将stdout重定向为输出到临时文件
在Python中,调用:subprocess.Popen(cmd, stdout = PIPE, stderr = PIPE, shell= true)的时候,如果调用的shell命令本身在执行之后会 ...
- 【Linux运维-集群技术进阶】Nginx+Keepalived+Tomcat搭建高可用/负载均衡/动静分离的Webserver集群
额.博客名字有点长.. . 前言 最终到这篇文章了,心情是有点激动的. 由于这篇文章会集中曾经博客讲到的全部Nginx功能点.包含主要的负载均衡,还有动静分离技术再加上这篇文章的重点.通过Keepal ...
- 【Linux磁盘优化管理--RAID和LVM】
在现阶段的企业环境中,为了数据的安全性及完整性必须要有一个合理的存储方案.面对着每秒可能产生超过几TB的数据,考虑到磁盘能不能实现 热冗余,及扩容,缩容.Linux给出了RAID(磁盘阵列)以及LVM ...
- 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk_buff,etc)
原文:http://blog.csdn.net/wenqian1991/article/details/46700177 通过前面的分析,可以发现,网络协议栈中的数据处理,都是基于各类结构体,所有有关 ...
- 【linux之链接,函数,随机数】
一.链接 硬链接(hard link):同一个文件使用了多个别名.新建文件是已经存在的一个别名,,当原文件删除时,新建的文件仍然可以使用.硬链接和原来的文件没有什么区别,而且共享一个inode号.通过 ...
随机推荐
- Python基础(filter)
arr = [1,2,3,1,1,3,6,9] def f1(x): if x > 2: return True arr1 = list(filter(f1,arr)) print(arr1)# ...
- Django笔记&教程 2-2 URL详细匹配规则
Django 自学笔记兼学习教程第2章第2节--URL详细匹配规则 点击查看教程总目录 本章第一节中我们简单介绍了URL与View关系 简单概括来说,网页请求的url会通过urls.py里面的urlp ...
- Spring Cloud Gateway实战之五:内置filter
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- [bzoj4942]整数
考虑暴力,即需要考虑如何实现$\pm 2^{k}$,相当于要找到之后的第一个0或者之前的第一个1(维护区间是否全0/1即可),然后区间重置,可以用线段树维护,复杂度为$o(900n)$(a的划分和线段 ...
- Electron跨平台程序破解
1. npm install asar -g 2. asar --version 如果有版本号就继续 3.找到需要解压的软件位置 在app.asar的地址输入 asar e app.asar tm ...
- Hi3516开发笔记(四):Hi3516虚拟机编译uboot、kernel、roofts和userdata以及分区表
若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121572767红胖子(红模仿)的博文大全:开发技术集合( ...
- 文本分类:Keras+RNN vs传统机器学习
摘要:本文通过Keras实现了一个RNN文本分类学习的案例,并详细介绍了循环神经网络原理知识及与机器学习对比. 本文分享自华为云社区<基于Keras+RNN的文本分类vs基于传统机器学习的文本分 ...
- Codeforces 632F - Magic Matrix(暴力 bitset or Prim 求最小生成树+最小瓶颈路)
题面传送门 开始挖老祖宗(ycx)留下来的东西.jpg 本来想水一道紫题作为 AC 的第 500 道紫题的,结果发现点开了道神题. 首先先讲一个我想出来的暴力做法.条件一和条件二直接扫一遍判断掉.先将 ...
- Codeforces 1491H - Yuezheng Ling and Dynamic Tree(分块)
Codeforces 题目传送门 & 洛谷题目传送门 *3400 的毒瘤 H 题,特意写个题解纪念一下( 首先对于这种数据结构不太好直接维护的东东可以考虑分块.然鹅我除了分块其他啥也没想到 我 ...
- Matlab指针数组
Matlab指针数组 前面博客Matlab指针中介绍了如何在Matlab中使用handle类型对象作为指针使用,本文则介绍一些使用这些类型指针的小技巧. 自定义类型的指针数组 在大部分编程语言中,我们 ...