2021-01-26 大数据课程笔记 day6

时间煮雨
@R星校长

Linux 中软件安装方式
rpm安装软件

rpm概述

RPM(RedHat Package Manager)安装管理
这个机制最早是由 Red Hat 开发出来,后来实在很好用,因此很多 distributions(发行版)就使用这个机制来作为软件安装的管理方式 。包括 Fedora , CentOS , SuSE 等等知名的开发商。

RPM 的优点

  1. RPM 内含已经编译过的程序与配置文件等数据,可以让用户免除重 新编译的困扰

  2. RPM 在被安装之前,会先检查系统的硬盘容量、操作系统版本等,可 避免文件被错误安装

  3. RPM 文件本身提供软件版本信息、相依属性软件名称、软件用途说明、软件所含文件等信息,便于了解软件

  4. RPM 管理的方式使用数据库记录 RPM 文件的相关参数,便于升级 、移除、查询与验证
    rpm默认安装的路径

  5. /etc 一些配置文件放置的目录,例如 /etc/crontab

  6. /usr/bin 一些可执行文件

  7. /usr/lib 一些程序使用的动态链接库

  8. /usr/share/doc 一些基本的软件使用手册与说明文件

  9. /usr/share/man 一些 man page( Linux 命令的随机帮助说明)文件

rpm 安装

rpm -ivh package_name
选项与参数:
-i :install的意思
-v :察看更细部的安装信息画面
-h :以安装信息列显示安装进度

  • 安装单个 rpm 包
 rpm -ivh package_name 
  • 安装多个 rpm 包
   rpm -ivh a.i386.rpm b.i386.rpm *.rpm 
  • 安装网上某个位置 rpm 包
 rpm -ivh http://website.name/path/pkgname.rpm

rpm 安装 jdk:

  1. 将上传到 /opt 目录下
[root@node1 opt]# ls
jdk-7u80-linux-x64.rpm  nginx  nginx-1.8.1  nginx-1.8.1.tar.gz
  1. 安装当前目录下的 jdk-7u80-linux-x64.rpm
[root@node1 opt]# rpm -ivh jdk-7u80-linux-x64.rpm 
Preparing...                ########################################### [100%]
   1:jdk                    ########################################### [100%]
Unpacking JAR files...
	rt.jar...
	jsse.jar...
	charsets.jar...
	tools.jar...
	localedata.jar...
	jfxrt.jar...
  1. 查找 java 安装目录的位置:
[root@node1 opt]# whereis java
java: /usr/bin/java
[root@node1 opt]# ll /usr/bin/java
lrwxrwxrwx 1 root root 26 11月 27 19:41 /usr/bin/java -> /usr/java/default/bin/java
[root@node1 opt]# cd /usr/java
[root@node1 java]# ls
default  jdk1.7.0_80  latest
[root@node1 java]# cd jdk1.7.0_80/
[root@node1 jdk1.7.0_80]# pwd
/usr/java/jdk1.7.0_80
  1. 配置环境变量
[root@node1 jdk1.7.0_80]# vim /etc/profile

加入以下两行代码:

export JAVA_HOME=/usr/java/jdk1.7.0_80
export PATH=$PATH:$JAVA_HOME/bin

在这里插入图片描述

  1. 让配置生效,使用.命令,或者 source 命令
[root@node1 jdk1.7.0_80]# source /etc/profile
  1. 测试安装配置是否成功
[root@node1 jdk1.7.0_80]# java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
[root@node1 jdk1.7.0_80]# jps
3926 Jps

成功!

rpm 安装:

  • redhat 提供了 rpm 管理系统
  • 已经编译的软件包:针对不同的平台系统编译目标软件包
  • 操作系统维护安装信息
  • 软件包包含依赖检查,这是人需要参与处理的。你得下载它需要的所有依赖包并安装,才能安装一个 rpm 软件。

rpm 查询:

   简单原理:rpm 在查询的时候,其实查询的地方是在 /var/lib/rpm/ 这个目录下的数据库文件

[root@node1 ~]# ll /var/lib/rpm/ 
total 58272 
-rw-r--r--. 1 root root  5500928 Mar  8 20:27 Basenames 
-rw-r--r--. 1 root root    12288 Mar  4 23:06 Conflictname 
-rw-r--r--  1 root root    24576 Mar  8 20:42 __db.001 
-rw-r--r--  1 root root   229376 Mar  8 20:42 __db.002
rpm 查询已安装软件,选项与参数:

-q :仅查询,后面接的软件名称是否有安装 
-qa :列出所有的,已经安装在本机 Linux 系统上面的所有软件名称 !!!
-qi :列出该软件的详细信息,包含开发商、版本和说明等 !!
-ql :列出该软件所有的文件与目录所在完整文件名 !!
-qc :列出该软件的所有配置文件 !
-qd :列出该软件的所有说明文件 
-qR :列出和该软件有关的相依软件所含的文件 
-qf :由后面接的文件名,找出该文件属于哪一个已安装的软件 

查询某个 RPM 文件内含有的信息:
-qp[icdlR]:

注意 -qp 后面接的所有参数以上面的说明一致。但用途仅在于找出 某个 RPM 文件内的信息,而非已安装的软件信息

案例1:查找是否安装 jdk

[root@node1 ~]# rpm -qa |grep jdk
jdk-1.7.0_80-fcs.x86_64

案例2:查询 jdk 所包含的文件及目录

[root@node1 ~]# rpm -ql jdk

案例3:查看 jdk 包的相关说明

[root@node1 ~]# rpm -qi jdk
Name        : jdk                          Relocations: /usr/java 
Version     : 1.7.0_80                   Vendor: Oracle Corporation
Release     : fcs                 Build Date: 2015年04月11日 星期六 11时15分36秒
Install Date: 2019年11月27日 星期三 19时41分29秒      
Build Host: sca00efd.us.oracle.com
Group       : Development/Tools             Source RPM: jdk-1.7.0_80-fcs.src.rpm
Size        : 219404663                       License: http://java.com/license
Signature   : (none)
Packager    : Java Software <jre-comments@java.sun.com>
URL         : URL_REF
Summary     : Java Platform Standard Edition Development Kit
Description :
The Java Platform Standard Edition Development Kit (JDK) includes both
the runtime environment (Java virtual machine, the Java platform classes
and supporting files) and development tools (compilers, debuggers,
tool libraries and other tools).

The JDK is a development environment for building applications, applets
and components that can be deployed with the Java Platform Standard
Edition Runtime Environment.

案例4:列出 iptables 的配置文件

[root@node1 ~]# rpm -qc iptables
/etc/sysconfig/iptables-config
(无显示说明不需要配置文件)

案例5:查看 apr 需要的依赖

[root@node1 ~]# yum install apr
[root@node1~]# rpm -qR apr

rpm 安装 MySQL

从 MySQL 官网下载 MySQL 的安装包:

https://downloads.mysql.com/archives/community/

需要下载 mysql 的四个 rpm 包:

mysql-community-client-5.7.19-1.el6.x86_64.rpm
mysql-community-common-5.7.19-1.el6.x86_64.rpm
mysql-community-libs-5.7.19-1.el6.x86_64.rpm
mysql-community-server-5.7.19-1.el6.x86_64.rpm

rpm 安装 mysql

1、 查找当前系统中安装的 MySQL:

[root@node1 ~]# rpm -qa | grep mysql
mysql-libs-5.1.71-1.el6.x86_64

2、 将上一步找到的 mysql 相关的包都删除

[root@node1 ~]# rpm -e mysql-libs-5.1.71-1.el6.x86_64
error: Failed dependencies:
	libmysqlclient.so.16()(64bit) is needed by (installed) postfix-2:2.6.6-2.2.el6_1.x86_64
	libmysqlclient.so.16(libmysqlclient_16)(64bit) is needed by (installed) postfix-2:2.6.6-2.2.el6_1.x86_64
	mysql-libs is needed by (installed) postfix-2:2.6.6-2.2.el6_1.x86_64

在这里插入图片描述

[root@node1 ~]# rpm -e --nodeps mysql-libs-5.1.71-1.el6.x86_64
[root@node1 ~]# rpm -qa | grep mysql

3、 检查并删除老版本 mysql 的开发头文件和库(如果有的话)

[root@node1 ~]# find / -name 'mysql*'
rm -fr /usr/lib/mysql
rm -fr /usr/include/mysql
rm -f /etc/my.cnf
rm -fr /var/lib/mysql
rm -fr /usr/share/mysql

注意:卸载后 /var/lib/mysql 中的数据及 /etc/my.cnf 不会删除,如果确定没用后就手工删除

4、 安装 perl

[root@node1 ~]# yum install perl -y

5、 下载 numactl-2.0.9-2.el6.x86_64.rpm 并安装

[root@node1 ~]# cd /opt
[root@node1 opt]# mkdir apps
[root@node1 apps]# rpm -ivh numactl-2.0.9-2.el6.x86_64.rpm

6、 安装 mysql(有顺序要求)

rpm -ivh mysql-community-common-5.7.19-1.el6.x86_64.rpm
rpm -ivh mysql-community-libs-5.7.19-1.el6.x86_64.rpm
rpm -ivh mysql-community-client-5.7.19-1.el6.x86_64.rpm
rpm -ivh mysql-community-server-5.7.19-1.el6.x86_64.rpm

a) 或执行:rpm -ivh mysql-community-*,让系统自己判断 rpm 安装顺序

7、 修改 /etc/my.cnf 文件,设置数据库的编码方式:

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character_set_server=utf8

8、 如果出现错误,请查看 /etc/my.cnf 文件中指定的错误 log 日志的文件

log-error=/var/log/mysqld.log

9、 启动 MySQL:service mysqld start
10、 找到随机密码:
   a) 在/var/log/mysqld.log中有一行:
   b) A temporary password is generated for root@localhost,后面就是随机密码
# mysql -uroot -p"yAe7QGVJ;HlR" 使用随机密码登录系统
11、 修改默认密码:

mysql> set global validate_password_policy=0;
mysql> set global validate_password_length=6;
mysql> set password for 'root'@'localhost'=password('123456');

12、 登陆 mysql 查看编码方式:
   a) mysql> show variables like ‘%character%’;
13、 给 root 设置远程登录权限

mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

14、 设置 msyql 开机启动

exit
chkconfig mysqld on

15、 安装完毕!

rpm 卸载

找出与 apr 有关的软件名称,并尝试移除 apr 这个软件

[root@node1 ~]# rpm -qa|grep apr
apr-1.3.9-5.el6_9.1.x86_64
[root@node1 ~]# rpm -e apr-1.3.9-5.el6_9.1.x86_64
[root@node1 ~]# rpm -qa|grep apr

yum 安装

epel 是什么?(了解)

全称:Extra Packages for Enterprise Linux,企业版 Linux 的额外软件包。它是 Fedora 小组维护的一个软件仓库项目,为 RHEL/CentOS 提供他们默认不提供的软件包。这个源兼容 RHEL 及像 CentOS 和 Scientific Linux 这样的衍生版本。
我们可以很容易地通过 yum 命令从 EPEL 源上获取上万个在 CentOS 自带源上没有的软件。EPEL 提供的软件包大多基于其对应的 Fedora 软件包,不会与企业版 Linux 发行版本的软件发生冲突或替换其文件。更多关于 EPEL 项目的细节可以到以下网站获取:https://fedoraproject.org/wiki/EPEL。
RHEL/CentOS 系统有许多第三方源,比较流行的比如 RpmForge,RpmFusion,EPEL,Remi 等等。然而需要引起注意的是,如果系统添加了多个第三方源,可能会因此产生冲突——一个软件包可以从多个源获取,一些源会替换系统的基础软件包,从而可能会产生意想不到的错误。已知的就有 Rpmforge 与 EPEL 会产生冲突。对于这些问题我们建议,调整源的优先权或者有选择性的安装源,但是这需要复杂的操作,如果你不确定如何操作,我们推荐你只安装一个第三方源。
在这里插入图片描述
yum命令:

yum repolist  #查看yum源
yum clean all
yum makecache
yum update  #更新系统使用该命令

查询:

yum list 列出系统中已经安装的和可以安装的包

yum list | grep mysql

yum search 在 yum 源搜索指定的包

yum search mysql

yum info 打印指定包的描述信息

yum info mysql-mmm-agent.noarch

安装和卸载:

yum install xxx
yum remove|erase xxx

yum 分组命令:

查询 yum 源中 rpm 包的组信息

yum grouplist

查看指定组的信息

yum groupinfo "Chinese Support"

yum groupinstall

yum groupinstall "Chinese Support"

yum groupremove 删除指定软件组

yum groupremove "Chinese Support"

yum groupupdate 更新指定软件组

yum groupupdate "Chinese Support"

关于软件源(扩展)

centos 切换软件源:
本地软件源
通过 nginx 发布内部软件源
让 Centos 的软件源指向其他源
![v

cd  /etc/yum.repos.d/
CentOS-Base.repo
本地软件源
cd  /etc/yum.repos.d/
cp  CentOS-Base.repo   localRepo.repo
mkdir  old
mv  CentOS-*  old     做备份

将原来的文件备份到一个位置

vim   localRepo.repo
  [base]
  name=CentOS-$releasever - Base
  #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
  baseurl=file:///mnt
  gpgcheck=0
  gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

插入 DVD 的 ISO 镜像文件 (CentOS-6.8-x86_64-bin-DVD1.iso),挂载到 /mnt 目录
在这里插入图片描述

mount  /dev/cdrom  /mnt
cd  /mnt

查看其中的内容

cd  /mnt/Packages
ls  -l  |  wc  -l

统计出该目录有多少个 rpm 包

yum clean all 清空本地元数据缓存
yum makecache 创建本地元数据缓存
yum repolist 查看元数据的具体信息

在这里插入图片描述

yum  install  pcre
yum  install  gcc

至此,本地 yum 源配置完成。

发布局域网 yum 源

tomcat 发布自定义的 yum 源

tomcat
解压tomcat的tar包:

tar -zxf apache-tomcat-7.0.68.tar.gz

首先将 dvd1 和 dvd2 的内容从 node2 的 /mnt 目录拷贝到 tomcat 的 webapps/ROOT/ 目录
在这里插入图片描述
启动 tomcat
在这里插入图片描述
在 node1 的 tomcat.repo 中进行配置:
在这里插入图片描述
配置 tomcat.repo:

[base]
name=CentOS-$releasever - Base - tomcat
baseurl=http://node2:8080
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
yum  clean  all
yum  makecache

就可以了

CentOS 使用其他源

如果使用清华的,请使用:
https://mirrors.tuna.tsinghua.edu.cn/help/centos/ 下的 centos6 的内容
将该内容贴到 /etc/yum.repos.d/mytsinghua.repo 中

yum  clean  all
yum  makecache

即可

使用阿里巴巴的源

查看帮助信息
在这里插入图片描述
在这里插入图片描述

CentOS

1、备份
在这里插入图片描述
2、下载新的 CentOS-Base.repo 到 /etc/yum.repos.d/

CentOS 6

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo

或者

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo

CentOS 7

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

或者

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

3、之后运行 yum makecache 生成缓存

4、其他
非阿里云 ECS 用户会出现 Couldn’t resolve host ‘mirrors.cloud.aliyuncs.com’ 信息,不影响使用。用户也可自行修改相关配置: eg:

sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.

需要 yum clean all
yum makecache

就可以使用 aliyun 的yum源了。

(了解)

Usage: yum [options] COMMAND

List of Commands:

check          Check for problems in the rpmdb
check-update   Check for available package updates
clean          移除缓存的数据
deplist        列出包的依赖
distribution-synchronization Synchronize installed packages to the latest available versions
downgrade      downgrade a package
erase          从系统中移除一个或几个包
groupinfo      打印软件组的细节信息
groupinstall   在系统中安装一组软件包
grouplist      列出可用的软件包
groupremove   从系统中移除一组软件包
help           Display a helpful usage message
history        Display, or use, the transaction history
info           Display details about a package or group of packages
install        在系统中安装一个或几个软件包
list           列出包信息或一组包的信息
load-transaction load a saved transaction from filename
makecache      生成元数据缓存
provides       哪个包提供了指定的值。
reinstall      重新安装一个软件包
repolist       打印配置的软件源
resolvedep     Determine which package provides the given dependency
search         搜索指定的包
shell          Run an interactive yum shell
update         Update a package or packages on your system
upgrade        Update packages taking obsoletes into account
version        Display a version for the machine and/or available repos.
正则表达式grep

hello.txt

hello world
are you ok?
areyou ok?
areyou are youok?
aaare you ok?
aare you ok
aaaare you ok
abcre you ok?
xxre you ok
are yyyou ok?
xk
zk
ok
yk
zzk
zxzxk
bxx
cxx
dxx
areyou are youok?
zk kz 1
kz zk 2
okk koo 3
zkkz
kzzk
cp /etc/profile  .
grep "after" profile #查找文件内的包含该单词的行
grep -n "after" profile #添加查找的行在文档的行号。

-v 表示不包含的

[root@bk1 ~]# grep -v "after" profile | grep "after"
[root@bk1 ~]# grep -v "pathmunge" profile | grep "after"
            if [ "$2" = "after" ] ; then

匹配符:

  1. \ 转义字符 + < >
  2. . 匹配任意单个字符
  3. [1234abc],[^1234],[1-5],[a-d] 字符序列单字符占位
  4. ^ 行首 ^.k
  5. $ 行尾 .k$
  6. <,>,<abc,abc>,<are> 单词首尾边界 okhelloworld ok hello world
  7. | 连接操作符,并集 (<are>)| (<you>)
  8. (,) 选择操作符
  9. \n 反向引用

匹配 are aare xre,0 到多个 a 字符

grep "a*re" hello.txt  

匹配 “a 任意单个字符 re”

grep "a.re" hello.txt

匹配 a 一个到多个任意字符 re

[root@bk1 ~]# grep "a+re" hello.txt

发现查询不出来,为什么?

重复操作符:

  1.  *    匹配0到多次
    
  2.  ?    匹配0到1次
    
  3.  +    匹配1到多次
    
  4. {n}   匹配n次
    
  5. {n,}  匹配n到多次
    
  6. {m,n} 匹配m到n次
    

与扩展正则表达式的区别: grep basic grep 默认工作于基本模式

-E 选项让 grep 工作于扩展模式

解决遗留问题:

[root@bk1 ~]# grep -E "a+re" hello.txt

或者

[root@bk1 ~]# grep "a\+re" hello.txt

基本正则表达式中元字符
?,+,{,|,(和)丢失了特殊意义,需要加\,反斜杠
?,+,{,|,(,以及),扩展模式不需要加反斜杠

所有字母和数字匹配自身,元字符可以添加\转义
[a-d] 匹配 abcd 中的一个
[^a-d] 匹配不是 abcd 中的任意一个的字符
需要注意:要使用 [a-d] 是abcd任意一个的传统方括号表达式的解释,需要设定环境变量:LC_ALL 的值是 C 。参考:https://www.cnblogs.com/wajika/p/6592659.html

开始:
匹配包含 bcd 中任意一个字符的行

grep "[b-d]" hello.txt

基本正则模式,查找带问号的行

grep "?" hello.txt

.不代表重复,任意一个字符

grep  "a.re"  hello.txt
grep  "a..re"  hello.txt

在这里插入图片描述

grep  "..re"  hello.txt
grep  "…re"  hello.txt

在这里插入图片描述
匹配 zk 和 xk

grep  "[xz]k"  hello.txt

在这里插入图片描述

匹配不是 zk 和 xk 的

grep  "\<[^zx]k"  hello.txt

匹配行首,该行第二个字符一定得是 k

grep  "^.k"  hello.txt

在这里插入图片描述
匹配行尾,

grep  ".k$"  hello.txt  #该行最少两个字符,最后一个是k

在这里插入图片描述
匹配单词边界

grep  "\<are\>"  hello.txt

在这里插入图片描述
匹配单词开头:

grep  "\<are"  hello.txt

在这里插入图片描述

匹配单词开头:

grep  "\<are"  hello.txt

在这里插入图片描述
匹配单词尾:

grep  "re\>"  hello.txt

在这里插入图片描述

grep   "\<a*re\>"  hello.txt    *表示0到多次,单词以a字符开头,或者不以a字符开头
grep    "\<you\>"  hello.txt

连接操作,取并集

grep  -E  "(\<a*re\>)|(\<you\>)"  hello.txt 

在这里插入图片描述

grep  -E  "a{3}"  hello.txt  匹配该行中 3 个 a 重复的

在这里插入图片描述

grep  -E  "a{3,}"  hello.txt
grep  -E  "a{3}"  hello.txt

在这里插入图片描述
匹配一个到多个 a

grep  -E  "a+"  hello.txt

匹配 0 到 1 次 a

grep  -E  "a?"  hello.txt

课后练习:
aaa? 匹配 aa,aaa

grep  -E  "\<aaa?re"  hello.txt #以aa或aaa开头并带有re的单词的行
aare  aaare  aaaare
grep  -E  "aaa?"  hello.txt  #包含aa或aaa的行

在这里插入图片描述

grep  "aaa\?"  hello.txt

在这里插入图片描述
匹配一次到多次:aaa 和 aaaa

grep  "aaa\+"  hello.txt

在这里插入图片描述
扩展模式:

grep  -E  "aaa+"  hello.txt

在这里插入图片描述
将匹配 1 次到多次的 + 再转义为 + 字符匹配

匹配 0 到任意多次

aaa* 匹配 aa,aaa,aaaa
在这里插入图片描述
匹配任意字符

grep -E  "*" hello.txt

反向引用

myhello
abbaabba
baabbaab
abbabaab
baababba
grep -E "(ab)(ba)\1\2" myhello  #匹配abba
grep -E "(ab)(ba)\2\1" myhello #匹配baab

bash

5000 台机器,有一个课件,想向每台机器上都上传一份该课件,如何做?
shell 就是一个 bash 程序

  • 解释器,启动器
  • 解释器:
     用户交互输入
     文本文件输入
    脚本本质:
  • #!/bin/bash
  • #!/usr/bin/python
    读取方式:
    bash/sh file
  • 当前shell:source file.
  • 新建子shell:/bin/bash file 或者 ./file.sh (需要chmod +x file.sh)
    .
    命令行中的命令都可以放到一个文件中!
    省的每次都得重新写大量的shell命令。

在当前shell执行脚本命令

type  source 
help  source
source  mysh.sh
./mysh.sh

[

root@bk1 ~]# bash
[root@bk1 ~]# echo $$   #打印当前bash的PID
1520
[root@bk1 ~]# exit
exit
[root@bk1 ~]# echo $$  #打印当前bash的PID
1280

[root@bk1 ~]# bash 
[root@bk1 ~]# pstree
init─┬─auditd───{auditd}
     ├─crond
     ├─master─┬─pickup
     │        └─qmgr
     ├─6*[mingetty]
     ├─rsyslogd───3*[{rsyslogd}]
     ├─sshd───sshd───bash───bash───pstree
     └─udevd───2*[udevd]
[root@bk1 ~]# exit
exit
[root@bk1 ~]# pstree
init─┬─auditd───{auditd}
     ├─crond
     ├─master─┬─pickup
     │        └─qmgr
     ├─6*[mingetty]
     ├─rsyslogd───3*[{rsyslogd}]
     ├─sshd───sshd───bash───pstree
     └─udevd───2*[udevd]

在这里插入图片描述
pstree -p
mysh.sh

#!/bin/bash
ls  -l  /
echo  "hello world!"

添加执行权限

chmod  +x  mysh.sh  #等价于a+x
./mysh.sh   #执行
bash  mysh.sh   #bash启动一个新进程,执行文件mysh.sh

mysh1.sh

#!/bin/bash
ls  -l  /
echo  "hello world!"
echo  $$
pstree
chmod  +x  mysh.sh
./mysh1.sh   #执行

让#!后跟的字符表示要启动的程序,该程序读取该文件执行。

awk.sh

#!/bin/awk -f
{split($3, date, "-");if (date[2] == "01") {name[$1]+=$5; if($2=="0"){role[$1]="Manager"}else{role[$1]="Worker"}}}  END{for(i in name){print i"\t"name[i]"\t"role[i]}}  
chmod  +x  awk.sh
./awk.sh   awk.txt

定义函数:

java语言:
public int methodName(int x,String name){
}
javascript:
Function mN(x,name)
Shell:
myshellname () {
   command1
command2
   command3
   ……
}

调用:
myshellname

总结:
bash是一个程序,shell是一个bash进程
bash是一个解释器,启动器
解释执行用户的输入指令,可以通过shell启动其他的进程

将要执行的命令放到一个文件中,
在文件的开头:
  #!/bin/bash
  #!/usr/bin/python
  #!/bin/awk -f
用于指定该脚本由哪个程序负责解释执行

当前shell执行脚本:source   .
子进程执行:bash  mysh.sh或者./mysh.sh(需要该文件具有可执行权限)
	
定义函数:
	funName() {
		各种命令
}

直接输入funName就可以执行了
io

重定向不是命令

  • 程序自身都有I/O
     0:标准输入
     1:标准输出
     2:错误输出
  • 控制程序I/O位置
  • 一切皆文件
     /proc/$$/fd
  • 程序是否处理I/O
  • 重定向绑定顺序:从左到右
ls / /hello 1> log.out
ls / /hello 1> log.out 2> log.err

输出重定向: 重定向从左到右绑定

ls  /  /hello   2>&1  1> mylog.log

从左向右绑定,错误输出绑定到标准输出,此时标准输出是输出到控制台,然后才是标准输出重定向到文件。两个重定向的绑定没有关系。
注意&1符号的替换,直接将输出绑定到资源,而不是绑定到文件描述符

ls  /  /hello   1> mylog1.log  2>&1

先让标准输出重定向到文件,然后将错误输出绑定到标准输出,也就是左边绑定的文件。

第二种写法
标准输出和错误输出都重定向到文件

ls  /  /hello   >& mylog2.log
ls  /  /hello  &> mylog3.log

将用户控制台的输入赋值给 aaa 变量
read 在不提供参数的时候,会将用户的输入存储在 REPLY 变量中
[

root@bk1 ~]# read
abc
[root@bk1 ~]# echo $REPLY
abc

如果提供了参数,则赋值给指定的参数

[root@bk1 ~]# read aaa
nihao
[root@bk1 ~]# echo $aaa
nihao 

[root@node1 day04]# vim rd.sh 
#!/bin/bash
read -p "请输入一个整数:" num
echo $num
read -p "再输入一个数:"
echo $REPLY

将标准输入重定向到字符串,read读取后赋值给指定的变量:
<<<将标准输入重定向到字符串

[root@bk1 ~]# read  aaa  0<<<"hello"
[root@bk1 ~]# echo $aaa
hello

用在脚本中用于向控制台打印n行

[root@bk1 ~]# cat 0<<CATEOF
> aaaaaa
> bbbbbb
> cccccccc
> CATEOF
aaaaaa
bbbbbb
cccccccc

vim catof.sh
#!/bin/bash
cat 0<<CATEOF
这里有一个bug
这个bug是index out of bounds exception
CATEOF

exec:使用指定的命令替换当前 shell 命令。
创建文件描述符:
以读写方式打开到 www.baidu.com 的 80 端口的 tcp 连接

exec 8<> /dev/tcp/www.baidu.com/80
echo -e "GET / HTTP/1.0\n" >& 8
cat <& 8
……
cd   /proc/$$/fd   #查看文件描述符
ll
echo  -e  "GET / HTTP/1.0\n"   >&8   #重定向到8文件描述符
cat   0<&  8  从文件描述符8读取信息
bash-var

bash 的变量

bash 中变量的类型:
  • 本地变量
  • 局部变量
  • 位置变量
  • 特殊变量
  • 环境变量
本地变量
  • 当前 shell 所有
  • 生命周期跟当前 shell 一样
a=99
echo  $a
99

myfunc() {
  myvar=99
  echo  $myvar
}
echo  $myvar    #访问不到
myfunc  #调用函数
echo  $myvar    #可以访问到

abc=sxt
echo  $abc
echo  "$abcisnothere"
echo  "${abc}isnothere"
局部变量:
  • 只能用于函数
  • local var=100
[root@bk1 ~]# myfunc(){
> local myvar=1001
> echo $myvar
> }
[root@bk1 ~]# myfunc
1001
[root@bk1 ~]# echo $myvar
位置变量:
  • $1, 2 , 2, 2{11}
  • 脚本
  • 函数
[root@node1 ~]# myfunc1(){
> echo $1
> }
[root@node1 ~]# myfunc1

[root@node1 ~]# myfunc1 hello
hello
[root@node1 ~]# myfunc2(){
> echo $4
> }
[root@node1 ~]# myfunc2 a b c

[root@node1 ~]# myfunc2 a b c d
d
[root@node1 ~]# myfunc3(){
> echo $13
> }
[root@node1 ~]# myfunc3 1 2 3 4 5 6 7 8 9 10 11 12 13
13
[root@node1 ~]# myfunc3 0 1 2 3 4 5 6 7 8 9 10 11 12 13
03
[root@node1 ~]# myfunc3 a 1 2 3 4 5 6 7 8 9 10 11 12 13
a3
[root@node1 ~]# myfunc3() {
> echo ${13}
> }
[root@node1 ~]# myfunc3 a 1 2 3 4 5 6 7 8 9 10 11 12 13
12
[root@node1 ~]# myfunc3 1 2 3 4 5 6 7 8 9 10 11 12 13
13
[root@node1 ~]#
脚本的位置变量:

在这里插入图片描述

特殊:
  • $#:位置参数个数
  • $*:参数列表,双引号引用为一个字符串 ./a a b c d e #“a b c d e”
     所有的参数作为一个字符串 5个参数作为一个字符串
  • $@:参数列表,双引号引用为单独的字符串 “a” “b” “c” “d” “e”
     所有的参数作为单个的字符串 5个参数作为五个字符串
  • $$:当前shell的PID:接收者
     $BASHPID:真实的值
     管道
  • $?:上一个命令的退出状态
     0:成功
     其他:失败
    在这里插入图片描述
    在这里插入图片描述
[root@node1 ~]# func() {
> echo $*
> }
[root@node1 ~]# func 1 2 a b d "hell owlrld"
1 2 a b d hell owlrld
[root@node1 ~]# func() {
> echo $@
> }
[root@node1 ~]# func 1 2 a b d "hell owlrld"
1 2 a b d hell owlrld

$$ 和 $BASHPID 的区别

$$ 在哪个进程中执行命令,该值就是哪个进程的 PID

$BASHPID 就是当前进程的 PID 真实值

在这里插入图片描述
在这里插入图片描述

[root@node1 ~]# [ -d mydir ] 
[root@node1 ~]# [ $? -eq 0 ] && echo "okok"
[root@node1 ~]# [ -d mydir ] 
[root@node1 ~]# [ $? -eq 0 ] || echo "okok"
okok

$?用于获取上一个命令的退出状态

mysh.sh 脚本:

echo  $1
echo  $2
echo  $12

echo  "--------------"
echo  $#
echo  $*
echo  $@
shell> source  mysh.sh  1 2 3 4 5 6 7 8 9 10 11 12 13
ls  /hello    #报错
echo   $?  查看退出状态
数组

数组定义:

Bash 提供了一维数组变量。任何变量都可以作为一个数组;内建命令 declare 可以显式地定义数组。数组的大小没有上限,也没有限制在连续对成员引用和赋值时有什么要求。数组以整数为下标,从 0 开始。

如果变量赋值时使用语法 name[subscript]=value,那么就会自动创建数组。 subscript 被当作一个算术表达式,结果必须是大于等于 0 的值。

数组赋值可以使用复合赋值的方式,形式是 name=(value1 … valuen),这里每个 value 的形式都是[subscript]=string。string 必须出现。如果出现了可选的括号和下标,将为这个下标赋值,否则被 赋值的元素的下标是语句中上一次赋值的下标加一。下标从 0 开始。这个语法也被内建命令 declare 所接受。单独的数组元素可以用上面介绍的语法 name[subscript]=value 来赋值。

数组的任何元素都可以用 $ {name[subscript]} 来引用。花括号是必须的,以避免和路径扩展冲突。如果subscript 是 @ 或是 ,它扩展为 name 的所有成员。这两种下标只有在双引号中才不同。在双引号中,$ {name[]} 扩展为一个词,由所有数组成员的值组成,用特殊变量 IFS 的 第 一 个 字 符 分 隔;$ {name[@]} 将 name 的每个成员扩展为一个词。如果数组没有成员,$ {name[@]} 扩展为空串。这种不同类似于特殊参数 * 和 @ 的扩展 (参见上面的 Special Parameters 段落)。${#name[subscript]} 扩展为 ${name[subscript]} 的长度。如果 subscript 是 * 或者是 @,扩展结果是数组中元素的个数。引用没有下标数组变量等价于引用元素 0。

内建命令 unset 用于销毁数组。unset name[subscript] 将销毁下标是 subscript 的 元 素 。 unset name, 这里 name 是一个数组,或者 unset name[subscript], 这里 subscript 是 * 或者是 @,将销毁整个数组。

内建命令 declare, local, 和 readonly 都能接受 -a 选项,从而指定一个数组。内建命令 read 可 以接受 -a 选项,从标准输入读入一列词来为数组赋值。内建命令 set 和 declare 使用一种可以重用为输入的格式来显示数组元素。

[root@bk1 ~]# sxt=(a  b  c)  #数组
[root@bk1 ~]# echo  $sxt
a
[root@bk1 ~]# echo  ${sxt[1]}
b
[root@bk1 ~]# echo  ${sxt[*]}
a b c
[root@bk1 ~]# echo  ${sxt[@]}
a b c
[root@bk1 ~]#

echo $sxt[1] 错误的写法

管道
[root@bk1 ~]# a=9
[root@bk1 ~]# echo  $a
9

[root@bk1 ~]# b=22  | echo  ok
ok
[root@bk1 ~]# echo  $b      #访问不到子进程的数据

[root@bk1 ~]#

管道两边的命令在当前 shell 的两个子进程中执行。

脚本:mysh.sh

#!/bin/bash
echo  $a
echo  "---------"

shell:

chmod  +x  mysh.sh
./mysh.sh
export  a    #将a导出为环境变量,子进程就可以访问了
./mysh.sh    #可以打印出a的值

子进程睡 20s ,在此期间修改环境变量的值,查看 export 是导出还是共享

脚本:mysh.sh

echo  $a
echo  "----------"
sleep  20
echo  $a

a=110 #主进程设置值
export a #导出变量
./mysh.sh & #后台执行子进程
a=220 #主进程修改值
export a #导出变量
子进程不能打印220,而是打印110

父进程修改值不会影响子进程的变化,子进程值的修改也不会影响父进程的值。
fork子进程,写时复制 copy on write

特殊性

$$ 意味着该脚本文件下运行的进程 ID。对于任何给定的脚本,在运行时,它会只有一个“主”进程ID。不管你有多少子 shell 调用,$$ 总是返回与脚本关联的第一个进程 ID。 BASHPID会告诉你的bash的当前实例的进程ID,因此在子shell会跟调用它的“顶级”的 bash 不同。

bash-basic
引用:
  • 双引号:弱引用,参数扩展
  • 单引号:强引用,不可嵌套
  • 花括号扩展不能被引用
  • 命令执行前删除引用
a=99
echo "$a"   # 99双引号引用,弱引用  
echo "\"$a\""   #"99"
echo '$a'    #$a  单引号引用,强引用

花括号扩展,创建 adir,bdir,cdir 三个目录

mkdir  ./{a,b,c}dir

花括号扩展,拷贝 /etc/profile 以及 /etc/init.d/network 到当前目录

cp  /etc/{profile,init.d/network}   ./
命令替换:

命令替换允许我们将 shell 命令的输出赋值给变量。它是脚本编程中的一个主要部分。
命令替换会创建子 shell 进程来运行相应的命令。子 shell 是由运行该脚本的 shell 所创建出来的一个独立的子进程。由该子进程执行的命令无法使用脚本中所创建的变量。

-	反引号:`ls -l`  ‘
-	/opt/apps    scp xx.gz node2:/opt/apps 
-	scp xx.gz node2:`pwd`
-	$(ls  -l  /) 可以嵌套

反引号提升扩展优先级,先执行反引号的内容,再执行其他的。
错误

myvar=echo "hello"

正确的:

myvar=`echo "hello"`

命令替换的嵌套

myvar=$(echo $(echo "hello world"))
myvar=$(echo "hello world")
myvar="hello world"
退出状态:
  • echo $?
逻辑判断:
-	command1  &&  command2
	如果command1退出状态是0,则执行command2
-	command1  ||  command2
	如果command1的退出状态不是0,则执行command2
[ -d /hello ]
test -d /hello || echo "文件夹/hello不存在"
test -d /bin && echo "文件夹/bin存在"
test -f profile && rm -f profile && touch profile
ls / && echo ok
ls / || echo ok
表达式
算术表达式
算术表达式:
-	let 算数运算表达式
	let  C=$A+$B   !!!
-	$[算术表达式]
	C=$[$A+$B]
-	$((算术表达式))!!!
	C=$((A+B))
-	expr算术表达式
	表达式中各操作数及运算符之间要有空格,同时要使用命令引用
	C=`expr $A  +  $B`
a=1
b=2
let c=$a+$b
echo $c
d=$((a+b))
echo $d
((a++))
echo  $a

前置++表示先自身++之后再参与计算
后置++表示先计算,再自身++

[root@node1 ~]# c=$((a+b)) && echo $c
4
 [root@node1 ~]# c=$((a--+b)) && echo $c
4
[root@node1 ~]# c=$((a--+b)) && echo $c
3
[root@node1 ~]# echo $a 
0
[root@node1 ~]# echo $b
2
[root@node1 ~]# c=$((--a+b)) && echo $c
1
[root@node1 ~]# c=$((a--+b)) && echo $c
1
[root@node1 ~]# echo $a $b
-2 2

[root@node1 shdemo]# e=$((a*b)) ???

条件表达式

条件表达式

  • [ 表达式 ]
  • test 表达式
  • [[ 表达式 ]]

help test

test  3  -gt  2
echo  $?
test  3  -gt  8
echo  $?
test  3  -gt  2  &&  echo  ok
等价于
[  3  -gt  2  ]  &&  echo  ok

test  3  -gt  8  &&  echo  ok
等价于
[  3  -gt  8  ]  &&  echo  ok

练习题

练习题:

-	添加用户      useradd  <username>
-	用户密码同用户名    passwd  --stdin  <username>  0<<<"username"
-	静默运行脚本
-	避免捕获用户接口
-	程序自定义输出        echo  "user  added!"
#! /bin/bash
useradd  $1   接收第一个参数作为用户名
使用管道将用户输入的第一个参数传递给passwd,passwd命令指定选项--stdin就不会捕获用户接口了,同时将passwd的标准输出重定向到/dev/null(数据黑洞)
passwd  --stdin  $1  >&  /dev/null
echo  "user  added!"

问题:
如果用户没有输入参数或参数个数不对怎么办?

#!/bin/bash
[  !  $#  -eq  1  ]  &&  echo  "Usage: ./$0 arg1"  &&  exit  2
useradd  $1
passwd  --stdin  $1  >&  /dev/null
echo "user  added"
shell> bash  mysh.sh  hello  执行
shell> id hello  查看hello用户是否添加成功
shell> userdel  -rf  hello  如果添加成功,就删除该用户,以继续后面的测试

问题:
如果要添加的用户已经存在怎么办?

#!/bin/bash
[  !  $#  -eq  1  ]  &&  echo  "Usage: ./$0 arg1"  &&  exit  2
#使用id命令检查,看返回值是否为0,如果是表示用户存在,提示并退出
id  $1  &> /dev/null  &&  echo "user  exists!"  &&  exit  3
useradd  $1
passwd  --stdin  $1  >&  /dev/null
echo "user  added"

adduser.sh    chmod 700 adduser.sh
./adduser.sh  user1
分支

help

  • if
  • while
  • for
  • case
if

• 单分支结构

if  [  条件判断  ] 
 then
    //命令
fi
if  [  条件判断  ];  then  
 条件成立执行,命令;     
fi  将if反过来写,就成为fi  结束if语句  

• 双分支结构

if  [  条件1  ];then  
   条件1成立执行,指令集1   
else  
   条件1不成执行指令集2;  
 fi

• 多分支结构

if  [  条件1  ];then  
   条件1成立,执行指令集1
elif  [  条件2  ];then  
 条件2成立,执行指令集2   
else  
   条件都不成立,执行指令集3 
 fi  

使用[命令判断

if  [  3  -gt  2  ];  then
  echo  ok 
fi
if  [  3  -gt  8  ];  
then  echo  ok; 
fi
[root@node1 ~]# cat sh01.sh 
#!/bin/bash
a=20
if [ $a -gt $1 ];
then
  echo "你输入的数字太小"
elif [ $a -eq $1 ];
then
  echo "恭喜哈,数字相等"
else
  echo "你输入的数字太大"
fi 
case
case  $变量名称  in   “值1")  
 程序段1  
 ;;    
“值2")   
 程序段2    
 ;;  
*)  
 exit  1  
 ;;   
esac 

案例:判断用户输入的是哪个数,1-7显示输入的数字,1显示 Mon,2 :Tue,3:Wed,4:Thu,5:Fir,6-7:weekend,其它值的时候,提示:please input [1,7],该如何实现?

#!/bin/bash
read -p "please input a number[1,7]:" num
case $num in
1)
    echo "Mon"
;;
2)
    echo "Tue"
;;
3)
    echo "Wed"
;;
4)
    echo "Thu"
;;
5)
    echo "Fir"
;;
[6-7])
    echo "weekend"
;;
*)
    echo "please input [1,7]"
;;

esac

或者
#!/bin/bash
# Mon,2 :Tue,3:Wed,4:Thu,5:Fir,6-7:weekend
case $1 in 1)
   echo "Mon"
   exit 0
;;
2)
   echo "Tue"
   exit 0
;;
3)
   echo "Wed"
   exit 0
;;
4)
   echo "Thu"
   exit 0
;;
5)
   echo "Fir"
   exit 0
;;
[6-7])
   echo "weekend"
   exit 0
;;
*)
   echo "please input [1,7]"
   exit 1
;;

esac
循环
while

• while 循环语句

while  [  condition  ]do    
 命令   
done 
或者
while  [  condition  ] 
 do    
 命令   
done 

案例一:每隔两秒打印系统负载情况,如何实现?

vim while1.sh

#!/bin/bash
while true
 do
   uptime   #系统负载情况
   sleep 2 #休眠2秒
 done

案例二:使用 while 循环,编写 shell 脚本,计算 1+2+3+…+100 的和并输出,如何实现?

vim while2.sh

#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]  #while和[之间要加一个空格  true则执行
do
  sum=$((sum+i))
  i=$((i+1)) #运算结果为变量赋值可以使用$(( … ))
done
echo "the result of '1+2+3+...+100' is $sum"

或者:

#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]  #while和[之间要加一个空格  true则执行
do
  let sum=$sum+$i
  let i=$i+1 #运算结果为变量赋值可以使用$(( … ))
done
echo "the result of '1+2+3+...+100' is $sum"
for 循环语句

• for…do…done 循环 
– 语法 

	for  变量名 in 变量取值列表     
	  	do  
			命令    
    	done  

提示:在此结构中 “in变量取值列表” 可省略,省略时相当于使用 for i in “$@”.

for 男人  in  世界的男人
do
   if [ 有房 ]&&[ 有车 ] &&[ 存款 ] &&[ 会做家务 ] &&[ 帅气 ];then
            echo “女生喜欢”
    else
            rm –f 男人
    fi;
done

直接列出元素的方法,比如:1 2 3 4 #=> 需要空格隔开

#!/bin/sh
for num in 1 2 3 4 
do 
  echo $num
done

使用大括号的方法

[root@bk1 ~]# echo {1..8}
1 2 3 4 5 6 7 8
[root@bk1 ~]# echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@bk1 ~]# echo 10.13.20.{1..3}
10.13.20.1 10.13.20.2 10.13.20.3
#!/bin/sh
for num in {1..4} 
do 
  echo $num
done

使用 seq –s 分隔符 起始 步长 终点 seq -s “ ” 2 2 100

[root@bk1 ~]# seq -s " " 1 1 5
1 2 3 4 5 
[root@bk1 ~]# vim for1.sh
#!/bin/sh
for num in `seq -s " " 1 1 5`
do
  echo $num
done
练习(作业)

练习题:

  • 用户给定路径
  • 输出文件大小最大的文件
  • 递归子目录
$IFS默认是空格,制表符和换行符
IFS=$'\n' 使用$获取\n换行符的ascii码作为IFS的值,此时分隔符就是换行符了。

步骤一:

思路:使用 du 命令加 -a 遍历用户指定目录($1获取)的所有文件,使用管道将结果传递给 sort,让 sort 使用数值序倒序排序,依次输出各个条目。
#!/bin/bash
oldIFS=$IFS
IFS=$'\n'  # 将for循环获取不同元素的标记修改为换行符
# for循环获取元素的时候使用空格区分各个不同的元素
for  item  in  `du  -a  $1 |  sort   -nr`; do
  echo  $item
done
IFS=$oldIFS    #用完后重置IFS变量的值。

因为要获取最大的文件,需要改进
改进:

#!/bin/bash
oldIFS=$IFS
IFS=$'\n'  # 将for循环获取不同元素的标记修改为换行符
# for循环获取元素的时候使用空格区分各个不同的元素
for  item  in  `du -a  $1 |  sort -nr`; do
  fileName=`echo  $item | awk '{print  $2}'`
  if  [  -f  $fileName  ]; then
      echo  $fileName
      break
  fi
done
IFS=$oldIFS    #用完后重置IFS变量的值。
Readfile(扩展)
问题:

循环遍历文件每一行:流程控制语句 IFS

  • 定义一个计数器
  • 打印num正好是文件行数

思路:

  • 管道
  • 重定向
  • 命令替换
    问题?
方案一:

思路:定义一个计数器,使用for循环从文件内容按行获取元素,每个元素是一行,在for循环中递增计数器用于计行数

#!/bin/bash
num=0
oldIFS=$IFS
IFS=$'\n'
# hello world are you ok
for  item  in  `cat  $1`; do
  echo $item
  ((num++))
done
echo "line number is :$num"
IFS=$oldIFS

在这里插入图片描述

方案二:

思路:先使用 wc 数出总行数,然后使用带下标的 for 循环分页遍历该文件,打印出每行,最后打印出总行数。

#!/bin/bash
num=0
lines=`cat $1 | wc  -l`
hello=$1
for  ((i=1;i<=lines;i++)); do
  line=`head  -$i  $hello |  tail  -1`
  echo $line
  ((num++))
done
echo "line number is :$num"
方案三:

思路:将 while 的 read 标准输入重定向到文件 file.txt ,按行读取,每读一行,就打读到的行记录,同时计数器 +1 ,最后得出总行数。

#!/bin/bash
num=0
while  read  line  ;do
   echo  $line
   ((num++))
done  <  $1
echo  "line number is : $num"
方案四:

思路:
使用管道命令,但是通过管道无法向父进程传递数据,需要将结果数据写到文件中,运行结束后,将数据读出来即可

#!/bin/bash
num=0    # 该num和管道后面的num不是一回事,因为num没有export
cat   $1  |  while  read  line; do
  echo  $line
  ((num++))    #即使当前环境没有num这个变量,((num++))一样可以使用
  done
echo  "line number is: $num"  > $2 #将结果重定向到一个文件
bash 的七步扩展:
1、	花括号 mkdir  -p  ./{a,b,c}dir   mkdir  -p  ./adir   ./bdir  ./cdir
2、	波浪线扩展  cd   ~god   cd  /home/god
3、	变量和参数替换  $ $1  $@ 
4、	命令替换:ls  -l  `echo  $path`
5、	算术扩展  num=$((3+4))   num=7   let num =$x+$y+5
6、	单词拆分: $IFS  通过$IFS对数据进行拆分
7、	路径 *(0到多个任意字符)  ?(1个字符)   .  +

在这里插入图片描述

shell script 脚本检查

• sh [-nvx] scripts.sh
• 选项与参数:
• -n :不执行script,仅查询语法的问题; !!
• -v :在执行script前,先将scripts的内容输出到屏幕上;
• -x :将使用到的script内容显示到屏幕上,这是很有用的参数; !!!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:精致技术 设计师:CSDN官方博客 返回首页
评论

打赏作者

Rich Dad

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值