signed

QiShunwang

“诚信为本、客户至上”

Linux学习笔记Part3 Shell和Shell script(1)

2021/3/21 0:58:26   来源:

一、Shell

1、shell 和 bash

(1)shell可以将我们输入的命令与内核(kernel)沟通

(2)目录/etc/shell:合法的shell会被写在此处

(3)bash是LInux系统的默认shell

(4)bash的优点:

  • 历史命令
  • 命令与文件补全功能
  • 命令别名设置
  • 程序化脚本(shell scripts)
  • 通配符

(5)查询是否为bash shell的内置命令:type

[root@www ~]# type [-tpa] name
选项与参数:
    :不加任何选项与参数时,type 会显示出 name 是外部命令还是 bash 内建命令
-t  :当加入 -t 参数时,type 会将 name 以底下这些字眼显示出他的意义:
      file    :表示为外部命令;
      alias   :表示该命令为命令别名所配置的名称;
      builtin :表示该命令为 bash 内建的命令功能;
-p  :如果后面接的 name 为外部命令时,才会显示完整文件名;
-a  :会由 PATH 变量定义的路径中,将所有含 name 的命令都列出来,包含 alias
范例一:查询一下 ls 这个命令是否为 bash 内建?
[root@www ~]# type ls
ls is aliased to `ls --color=tty' <==未加任何参数,列出 ls 的最主要使用情况
[root@www ~]# type -t ls
alias                             <==仅列出 ls 运行时的依据
[root@www ~]# type -a ls
ls is aliased to `ls --color=tty' <==最先使用 aliase
ls is /bin/ls                     <==还有找到外部命令在 /bin/ls

范例二:那么 cd 呢?
[root@www ~]# type cd
cd is a shell builtin             <==看到了吗? cd 是 shell 内建命令

(6)如果命令太长,可以使用\来切换到下一行输入

范例:如果命令串太长的话,如何使用两行来输出?
[vbird@www ~]# cp /var/spool/mail/root /etc/crontab \
> /etc/fstab /root

2、Shell变量功能

(1)什么是变量?

​ 让某一个特定字符串代表不固定的内容,用一个简单的 “字眼” 来取代另一个比较复杂或者是容易变动的数据

(2)变量的使用与设置

变量在使用时必须在变量名前加$
echo命令:将变量显示在屏幕
[root@www ~]# echo $variable
[root@www ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@www ~]# echo ${PATH}
当一个变量名称尚未被配置时,默认的内容是空的
使用赋值运算法=设置变量:
[root@www ~]# echo $myname
       <==这里并没有任何数据~因为这个变量尚未被配置!是空的!
[root@www ~]# myname=VBird
[root@www ~]# echo $myname
VBird  <==出现了!因为这个变量已经被配置了!
变量设置规则:
  • 变量与变量内容以一个等号=来连结,如下所示:myname=VBird

  • 等号两边不能直接接空格符,如下所示为错误:myname = VBird或myname=VBird Tsai

  • 变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:2myname=VBird

  • 变量内容若有空格符可使用双引号『"』或单引号『’』将变量内容结合起来,但双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:var="lang is $LANG"则echo $var可得lang is en_US
    单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:var='lang is $LANG’则echo $var可得lang is $LANG

  • 可用跳脱字符 \ 将特殊符号(如 [Enter], $, , 空格符, '等)变成一般字符;

  • 在一串命令中,还需要藉由其他的命令提供的信息,可以使用反单引号命令 ( 命 令 ) 。 特 别 注 意 , 那 个 ‘ 是 键 盘 上 方 的 数 字 键 1 左 边 那 个 按 键 , 而 不 是 单 引 号 ! 例 如 想 要 取 得 核 心 版 本 的 配 置 : v e r s i o n = (命令)。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的配置:version= ()1version=(uname -r)再echo $version可得2.6.18-128.el5

  • 若该变量为扩增变量内容时,则可用 “$变量名称” 或 变 量 累 加 内 容 , 如 下 所 示 : P A T H = " {变量} 累加内容,如下所示:PATH=" PATH="PATH":/home/bin

  • 若该变量需要在其他子程序运行,则需要以 export 来使变量变成环境变量:export PATH

  • 通常大写字符为系统默认变量,自行配置变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;

  • 取消变量的方法为使用 unset :unset 变量名称例如取消 myname 的配置:unset myname

范例一:配置一变量 name ,且内容为 VBird
[root@www ~]# 12name=VBird
-bash: 12name=VBird: command not found  <==屏幕会显示错误!因为不能以数字开头!
[root@www ~]# name = VBird            <==还是错误!因为有空白!
[root@www ~]# name=VBird              <==OK 的啦!

范例二:承上题,若变量内容为 VBird's name 呢,就是变量内容含有特殊符号时:
[root@www ~]# name=VBird's name  
# 单引号与双引号必须要成对,在上面的配置中仅有一个单引号,因此当你按下 enter 后,
# 你还可以继续输入变量内容。这与我们所需要的功能不同,失败啦!
# 记得,失败后要复原请按下 [ctrl]-c 结束!
[root@www ~]# name="VBird's name"    <==OK 的啦!
# 命令是由左边向右找→,先遇到的引号先有用,因此如上所示,单引号会失效!
[root@www ~]# name='VBird's name'    <==失败的啦!
# 因为前两个单引号已成对,后面就多了一个不成对的单引号了!因此也就失败了!
[root@www ~]# name=VBird\'s\ name     <==OK 的啦!
# 利用反斜杠 (\) 跳脱特殊字符,例如单引号与空格键,这也是 OK 的啦!

范例三:我要在 PATH 这个变量当中『累加』:/home/dmtsai/bin 这个目录
[root@www ~]# PATH=$PATH:/home/dmtsai/bin
[root@www ~]# PATH="$PATH":/home/dmtsai/bin
[root@www ~]# PATH=${PATH}:/home/dmtsai/bin
# 上面这三种格式在 PATH 里头的配置都是 OK 的!但是底下的例子就不见得啰!

范例四:承范例三,我要将 name 的内容多出 "yes" 呢?
[root@www ~]# name=$nameyes  
# 知道了吧?如果没有双引号,那么变量成了啥?name 的内容是 $nameyes 这个变量!
# 呵呵!我们可没有配置过 nameyes 这个变量吶!所以,应该是底下这样才对!
[root@www ~]# name="$name"yes
[root@www ~]# name=${name}yes  <==以此例较佳!

范例五:如何让我刚刚配置的 name=VBird 可以用在下个 shell 的程序?
[root@www ~]# name=VBird
[root@www ~]# bash        <==进入到所谓的子程序
[root@www ~]# echo $name  <==子程序:再次的 echo 一下;
       <==嘿嘿!并没有刚刚配置的内容喔!
[root@www ~]# exit        <==子程序:离开这个子程序
[root@www ~]# export name
[root@www ~]# bash        <==进入到所谓的子程序
[root@www ~]# echo $name  <==子程序:在此运行!
VBird  <==看吧!出现配置值了!
[root@www ~]# exit        <==子程序:离开这个子程序
什么是子程序呢?就是说,在我目前这个 shell 的情况下,去激活另一个新的 shell ,新的那个 shell 就是子程序啦!在一般的状态下,父程序的自定义变量是无法在子程序内使用的。但是透过 export 将变量变成环境变量后,就能够在子程序底下应用了

范例六:如何进入到您目前核心的模块目录?
[root@www ~]# cd /lib/modules/`uname -r`/kernel
[root@www ~]# cd /lib/modules/$(uname -r)/kernel
其实上面的命令可以说是作了两次动作,亦即是:
先进行反单引号内的动作uname -r并得到核心版本为 2.6.18-128.el5
将上述的结果带入原命令,故得命令为:cd /lib/modules/2.6.18-128.el5/kernel/

范例七:取消刚刚配置的 name 这个变量内容
[root@www ~]# unset name

(3)环境变量的功能

env指令:观察环境变量
范例一:列出目前的 shell 环境下的所有环境变量与其内容。
[root@www ~]# env
HOSTNAME=www.vbird.tsai    <== 这部主机的主机名
TERM=xterm                 <== 这个终端机使用的环境是什么类型
SHELL=/bin/bash            <== 目前这个环境下,使用的 Shell 是哪一个程序?
HISTSIZE=1000              <== 记录命令的笔数在 CentOS 默认可记录 1000 笔
USER=root                  <== 使用者的名称啊!
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:
or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0
0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=
00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3
1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00
;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些颜色显示
MAIL=/var/spool/mail/root  <== 这个用户所取用的 mailbox 位置
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:
/root/bin                  <== 不再多讲啊!是运行文件命令搜寻路径
INPUTRC=/etc/inputrc       <== 与键盘按键功能有关。可以配置特殊按键!
PWD=/root                  <== 目前用户所在的工作目录 (利用 pwd 取出)
LANG=en_US                 <== 这个与语系有关,底下会再介绍!
HOME=/root                 <== 这个用户的家目录啊!
_=/bin/env                 <== 上一次使用的命令的最后一个参数(或命令本身)
常用环境变量分析:
  • HOME

    代表用户的家目录。可以使用 cd ~ 去到自己的家目录,或者利用 cd 就可以直接回到用户家目录。那就是取用这个变量~ 有很多程序都可能会取用到这个变量的值

  • SHELL
    告知我们,目前这个环境使用的 SHELL 是哪支程序? Linux 默认使用 /bin/bash

  • HISTSIZE
    这个与历史命令有关,我们曾经下达过的命令可以被系统记录下来,而记录的笔数则是由这个值来配置的。

  • MAIL
    当我们使用 mail 这个命令在收信时,系统会去读取的邮件信箱文件 (mailbox)

  • PATH
    就是运行文件搜寻的路径,目录与目录中间以冒号(:)分隔, 由于文件的搜寻是依序由 PATH 的变量内的目录来查询,所以,目录的顺序非常重要

  • LANG
    语系数据,很多信息都会用到, 举例来说,当我们在启动某些 perl 的程序语言文件时,他会主动的去分析语系数据文件, 如果发现有他无法解析的编码语系,可能会产生错误。一般来说,我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8

  • RANDOM
    随机数的变量,目前大多数的Linux发行版都会有随机数生成器,那就是 /dev/random 这个文件。 我们可以通过这个随机数文件相关的变量 ($RANDOM) 来随机取得随机数值。在 BASH 的环境下,这个 RANDOM 变量的内容,介于 0~32767 之间,所以,你只要 echo $RANDOM 时,系统就会主动的随机取出一个介于 0~32767 的数值。如果想要使用 0~9 之间的数值呢?利用 declare 宣告数值类型, 然后这样做就可以了:

[root@www ~]# declare -i number=$RANDOM*10/32768 ; echo $number
8   <== 此时会随机取出 0~9 之间的数值
set指令:观察环境变量与自定义指令
[root@www ~]# set
BASH=/bin/bash           <== bash 的主程序放置路径
BASH_VERSINFO=([0]="3" [1]="2" [2]="25" [3]="1" [4]="release" 
[5]="i686-redhat-linux-gnu")      <== bash 的版本
BASH_VERSION='3.2.25(1)-release'  <== 也是 bash 的版本
COLORS=/etc/DIR_COLORS.xterm      <== 使用的颜色纪录文件
COLUMNS=115              <== 在目前的终端机环境下,使用的字段有几个字符长度
HISTFILE=/root/.bash_history      <== 历史命令记录的放置文件,隐藏档
HISTFILESIZE=1000        <== 存起来(与上个变量有关)的文件之命令的最大纪录笔数。
HISTSIZE=1000            <== 目前环境下,可记录的历史命令最大笔数。
HOSTTYPE=i686            <== 主机安装的软件主要类型。我们用的是 i686 兼容机器软件
IFS=$' \t\n'             <== 默认的分隔符
LINES=35                 <== 目前的终端机下的最大行数
MACHTYPE=i686-redhat-linux-gnu    <== 安装的机器类型
MAILCHECK=60             <== 与邮件有关。每 60 秒去扫瞄一次信箱有无新信
OLDPWD=/home             <== 上个工作目录。我们可以用 cd - 来取用这个变量。
OSTYPE=linux-gnu         <== 操作系统的类型
PPID=20025               <== 父程序的 PID (会在后续章节才介绍)
PS1='[\u@\h \W]\$ '      <== PS1 就厉害了。这个是命令提示字符,也就是我们常见的
                             [root@www ~]# 或 [dmtsai ~]$ 的配置值,可以更动的
PS2='> '                 <== 如果你使用跳脱符号 (\) 第二行以后的提示字符也
name=VBird               <== 刚刚配置的自定义变量也可以被列出来
$                        <== 目前这个 shell 所使用的 PID
?                        <== 刚刚运行完命令的回传值。
  • 不论是否为环境变量,只要跟我们目前这个 shell 的操作接口有关的变量, 通常都会被配置为大写字符,也就是说,基本上,在 Linux 默认的情况中,使用{大写的字母}来配置的变量一般为系统内定需要的变量
重要的系统变量:
  • PS1
    命令提示字符, 当我们每次按下 [Enter] 按键去运行某个命令后,最后要再次出现提示字符时, 就会主动去读取这个变量值了。PS1 内显示的是一些特殊符号,这些特殊符号可以显示不同的信息, 每个 Linux发行版的bash 默认的 PS1 变量内容可能有些许的差异, 可以用 man bash 去查询一下 PS1 的相关说明

    \d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"
    \H :完整的主机名。
    \h :仅取主机名在第一个小数点之前的名字
    \t :显示时间,为 24 小时格式的HH:MM:SS
    \T :显示时间,为 12 小时格式的HH:MM:SS
    \A :显示时间,为 24 小时格式的HH:MM
    \@ :显示时间,为 12 小时格式的am/pm样式
    \u :目前使用者的账号名称,如roo』;
    \v :BASH 的版本信息,如测试主板本为 3.2.25,仅取3.2显示
    \w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;
    \W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名
    \# :下达的第几个命令。
    \$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ 
    

    CentOS默认的PS1内容为[\u@\h \W]$

  • ** ∗ ∗ < b r > 关 于 本 s h e l l 的 P I D 。 **<br>关于本shell的PID。 <br>shellPID本身也是个变量,代表的是目前这个 Shell 的线程代号,亦即是所谓的 PID (Process ID)。想要知道我们的 shell 的 PID ,就可以用:echo $$即可,出现的数字就是你的 PID 号码。

  • ?
    关于上个运行命令的回传值。问号也是一个特殊的变量,在 bash 里面这个变量很重要,这个变量是:上一个运行的命令所回传的值。‘’当我们运行某些命令时, 这些命令都会回传一个运行后的代码。一般来说,如果成功的运行该命令, 则会回传一个 0 值,如果运行过程发生错误,就会回传错误代码。一般就是以非为 0 的数值来取代。

[root@www ~]# echo $SHELL
/bin/bash                                  <==可顺利显示,没有错误
[root@www ~]# echo $?
0                                          <==因为没问题,所以回传值为 0
[root@www ~]# 12name=VBird
-bash: 12name=VBird: command not found     <==发生错误了,bash回报有问题
[root@www ~]# echo $?
127                                        <==因为有问题,回传错误代码(非为0)
# 错误代码回传值依据软件而有不同,我们可以利用这个代码来搜寻错误的原因
[root@www ~]# echo $?
0
# 这是因为 "?" 只与上一个运行命令有关,
# 所以,我们上一个命令是运行 echo $? ,所以是 0
  • OSTYPE, HOSTTYPE, MACHTYPE
    主机硬件与核心的等级。目前个人计算机的 CPU 主要分为 32/64 位,其中 32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。 由于不同等级的 CPU 命令集不太相同,因此你的软件可能会针对某些 CPU 进行优化,以求取较佳的软件性能。 所以软件就有 i386, i686 及 x86_64 之分。以目前的主流硬件来说,几乎都是 x86_64 的天下. 但是毕竟旧机器还是非常多.较高阶的硬件通常会向下兼容旧有的软件,但较高阶的软件可能无法在旧机器上面安装!
export指令:自定义变量转成环境变量
  • bash子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量,如果需要将自定义变量传递给子进程,需要调用export指令将自定义变量转成环境变量。
  • export使用方法:
[root@www ~]# export 变量名称
  • 如果仅下达 export 而没有接变量时,那么此时将会把所有的环境变量打印出来
[root@www ~]# export
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="localhost"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="en_US"
declare -x LOGNAME="root"
...

(4)影响显示结果的语系变量(locale)

​ 当我们使用 man command 的方式去查询某个数据的说明文件时,该说明档的内容可能会因为我们使用的语系不同而产生乱码。 另外,利用 ls 查询文件的时间时,也可能会有乱码出现在时间的部分,那个问题其实就是语系的问题。

查询Linux支持哪些语系:
[root@www ~]# locale -a
....(前面省略)....
zh_CN
zh_CN.gb18030     <==大五码的中文编码
zh_CN.gb2312
zh_CN.utf8     <==万国码的中文编码
zu_ZA
zu_ZA.iso88591
zu_ZA.utf8
显示当前语系设置:
[root@www ~]# locale
LANG=en_US.UTF-8  <==主语言的环境
LC_CTYPE="en_US.UTF-8"  <==字符(文字)辨识的编码
LC_NUMERIC=zh_CN.UTF-8  <==数字系统的显示信息
LC_TIME=zh_CN.UTF-8 <==时间系统的显示数据
LC_COLLATE="en_US.UTF-8"  <==字符串的比较与排序等
LC_MONETARY=zh_CN.UTF-8   <==币值格式的显示等
LC_MESSAGES="en_US.UTF-8" <==信息显示的内容,如菜单、错误信息等
LC_PAPER=zh_CN.UTF-8
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT=zh_CN.UTF-8
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL= <==整体语系的环境

可以逐一配置每个与语系有关的变量数据,但事实上,如果其他的语系变量都未配置, 且你有配置 LANG 或者是 LC_ALL 时,则其他的语系变量就会被这两个变量所取.

(5)变量的有效范围

  • 当启动一个 shell,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用
  • 若在父程序利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量);
  • 当加载另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子 shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。

(6)变量的键盘读取、数组与声明:read、array、declare

read指令:

​ 读取来自键盘输入的变量

[root@www ~]# read [-pt] variable
选项与参数:
-p  :后面可以接提示字符!
-t  :后面可以接等待的秒数!』这个比较有趣~不会一直等待使用者啦!
范例一:让用户由键盘输入一内容,将该内容变成名为 atest 的变量
[root@www ~]# read atest
This is a test        <==此时光标会等待你输入!请输入左侧文字看看
[root@www ~]# echo $atest
This is a test          <==你刚刚输入的数据已经变成一个变量内容!
范例二:提示使用者 30 秒内输入自己的大名,将该输入字符串作为名为 named 的变量内容
[root@www ~]# read -p "Please keyin your name: " -t 30 named
Please keyin your name: VBird Tsai   <==会有提示字符
[root@www ~]# echo $named
VBird Tsai        <==输入的数据又变成一个变量的内容了
decare、typeset指令:

​ declare 或 typeset 是一样的功能,就是设置变量的类型。

​ 如果使用 declare 后面并没有接任何参数,那么 bash 就会主动的将所有的变量名称与内容通通叫出来,就好像使用 set 一样.

[root@www ~]# declare [-aixr] variable
选项与参数:
-a  :将后面名为 variable 的变量定义成为数组 (array) 类型
-i  :将后面名为 variable 的变量定义成为整数数字 (integer) 类型
-x  :用法与 export 一样,就是将后面的 variable 变成环境变量;
-r  :将变量配置成为 readonly 类型,该变量不可被更改内容,也不能 unset
范例一:让变量 sum 进行 100+300+50 的加总结果
[root@www ~]# sum=100+300+50
[root@www ~]# echo $sum
100+300+50  <==文字型态的变量属性
[root@www ~]# declare -i sum=100+300+50
[root@www ~]# echo $sum
450        

​ bash对于变量的基本定义:

  • 变量类型默认为『字符串』,所以若不指定变量类型,则 1+2 为一个字符串而不是计算式。 所以上述第一个运行的结果才会出现那个情况的;
  • bash 环境中的数值运算,默认最多仅能到达整数形态,所以 1/3 结果是 0
范例二:将 sum 变成环境变量
[root@www ~]# declare -x sum
[root@www ~]# export | grep sum
declare -ix sum="450"  <==包括有 i 与 x 的定义

范例三:让 sum 变成只读属性,不可更动
[root@www ~]# declare -r sum
[root@www ~]# sum=tesgting
-bash: sum: readonly variable  <==不能改这个变量

范例四:让 sum 变成非环境变量的自定义变量吧
[root@www ~]# declare +x sum  <== 将 - 变成 + 可以进行『取消』动作
[root@www ~]# declare -p sum  <== -p 可以单独列出变量的类型
declare -ir sum="450" <== 看吧!只剩下 i, r 的类型,不具有 x 

​ 如果你不小心将变量配置为只读,通常得要注销再登陆才能复原该变量的类型

数组(array)变量类型:

​ 在 bash 里头,数组的配置方式是:

var[index]=content

范例:配置上面提到的 var[1] ~ var[3] 的变量。
[root@www ~]# var[1]="small min"
[root@www ~]# var[2]="big min"
[root@www ~]# var[3]="nice min"
[root@www ~]# echo "${var[1]}, ${var[2]}, ${var[3]}"
small min, big min, nice min

(7)与文件系统及程序的限制关系: ulimit

​ bash 是可以调用ulimit指令限制用户的某些系统资源的,包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等

[root@www ~]# ulimit [-SHacdfltu] [配额]
选项与参数:
-H  :hard limit ,严格的配置,必定不能超过这个配置的数值;
-S  :soft limit ,警告的配置,可以超过这个配置值,但是若超过则有警告信息。
      在配置上,通常 soft 会比 hard 小,举例来说,soft 可配置为 80 而 hard 
      配置为 100,那么你可以使用到 90 (因为没有超过 100),但介于 80~100 之间时,
      系统会有警告信息通知你!
-a  :后面不接任何选项与参数,可列出所有的限制额度;
-c  :当某些程序发生错误时,系统可能会将该程序在内存中的信息写成文件(除错用),
      这种文件就被称为核心文件(core file)。此为限制每个核心文件的最大容量。
-f  :此 shell 可以创建的最大文件容量(一般可能配置为 2GB)单位为 Kbytes
-d  :程序可使用的最大断裂内存(segment)容量;
-l  :可用于锁定 (lock) 的内存量
-t  :可使用的最大 CPU 时间 (单位为秒)
-u  :单一用户可以使用的最大程序(process)数量。

范例一:列出你目前身份(假设为root)的所有限制数据数值
[root@www ~]# ulimit -a
core file size          (blocks, -c) 0          <==只要是 0 就代表没限制
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited  <==可创建的单一文件的大小
pending signals                 (-i) 11774
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024       <==同时可开启的文件数量
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 11774
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

范例二:限制用户仅能创建 10MBytes 以下的容量的文件
[root@www ~]# ulimit -f 10240
[root@www ~]# ulimit -a
file size               (blocks, -f) 10240 <==最大量为10240Kbyes,相当10Mbytes
[root@www ~]# dd if=/dev/zero of=123 bs=1M count=20
File size limit exceeded <==尝试创建 20MB 的文件,结果失败了

(7)变量内容的删除、取代、替换、可选

变量内容的删除与替换:
范例一:先让小写的 path 自定义变量配置的与 PATH 内容相同
[root@www ~]# path=${PATH}
[root@www ~]# echo $path
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

范例二:假设我不喜欢 kerberos,所以要将前两个目录删除掉,如何显示?
[root@www ~]# echo ${path#/*kerberos/bin:}
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
${variable#/*kerberos/bin:}
   上面的特殊字体部分是关键词!用在这种删除模式所必须存在的

${variable#/*kerberos/bin:}
   这就是原本的变量名称,以上面范例二来说,这里就填写 path 这个『变量名称』啦!

${variable#/*kerberos/bin:}
   这是重点!代表『从变量内容的最前面开始向右删除』,且仅删除最短的那个

${variable#/*kerberos/bin:}
   代表要被删除的部分,由于 # 代表由前面开始删除,所以这里便由开始的 / 写起。
   需要注意的是,我们还可以透过通配符 * 来取代 0 到无穷多个任意字符
   
以上面范例二的结果来看, path 这个变量被删除后内容如下所示:
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 
范例三:我想要删除前面所有的目录,仅保留最后一个目录
[root@www ~]# echo ${path#/*:}
/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:
/root/bin     <==这两行其实是同一行啦!
# 由于一个 # 仅删除掉最短的那个,因此他删除的情况可以用底下的删除线来看:
# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

[root@www ~]# echo ${path##/*:}
/root/bin
# 嘿!多加了一个 # 变成 ## 之后,他变成删除掉最长的那个数据
  • #:符合取代文字的『最短的』那一个;
  • ##:符合取代文字的『最长的』那一个
范例四:我想要删除最后面那个目录,亦即从 : 到 bin 为止的字符串
[root@www ~]# echo ${path%:*bin}
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin  <==注意啊!最后面一个目录不见去!
# 这个 % 符号代表由最后面开始向前删除!所以上面得到的结果其实是来自如下:
# /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
# /usr/sbin:/usr/bin:/root/bin  <==这两行其实是同一行啦!

范例五:那如果我只想要保留第一个目录呢?
[root@www ~]# echo ${path%%:*bin}
/usr/kerberos/sbin
# 同样的,%% 代表的则是最长的符合字符串

范例六:将 path 的变量内容内的 sbin 取代成大写 SBIN:
[root@www ~]# echo ${path/sbin/SBIN}
/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:
/usr/sbin:/usr/bin:/root/bin
# 这个部分就容易理解的多了!关键词在于那两个斜线,两斜线中间的是旧字符串
# 后面的是新字符串,所以结果就会出现如上述的特殊字体部分啰!

[root@www ~]# echo ${path//sbin/SBIN}
/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/SBIN:/usr/local/bin:/SBIN:/bin:
/usr/SBIN:/usr/bin:/root/bin
# 如果是两条斜线,那么就变成所有符合的内容都会被取代

​ 总结:

变量配置方式说明
KaTeX parse error: Expected '}', got '#' at position 4: {变量#̲关键词}<br/>{变量##关键词}若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除
若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除
KaTeX parse error: Expected '}', got 'EOF' at end of input: {变量%关键词}<br/>{变量%%关键词}若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除
若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除
变 量 / 旧 字 符 串 / 新 字 符 串 < b r / > {变量/旧字符串/新字符串}<br/> //<br/>{变量//旧字符串/新字符串}若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串取代』
若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串取代』
变量的测试与内容替换:
范例一:测试一下是否存在 username 这个变量,若不存在则给予 username 内容为 root
[root@www ~]# echo $username
           <==由于出现空白,所以 username 可能不存在,也可能是空字符串
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
root       <==因为 username 没有配置,所以主动给予名为 root 的内容。
[root@www ~]# username="vbird tsai" <==主动配置 username 的内容
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
vbird tsai <==因为 username 已经配置了,所以使用旧有的配置而不以 root 取代
  • new_var=${old_var-content} 新的变量,主要用来取代旧变量。新旧变量名称其实常常是一样的

  • new_var=${old_var-content} 这是本范例中的关键词部分!必须要存在的

  • new_var=${old_var-content} 旧的变量,被测试的项目!

  • new_var=${old_var-content} 变量的内容,在本范例中,这个部分是在给予未配置变量的内容

范例二:若 username 未配置或为空字符串,则将 username 内容配置为 root
[root@www ~]# username=""
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
      <==因为 username 被配置为空字符串了,所以当然还是保留为空字符串
[root@www ~]# username=${username:-root}
[root@www ~]# echo $username
root  <==加上『 : 』后若变量内容为空或者是未配置,都能够以后面的内容替换

在大括号内有没有冒号『 : 』的差别是很大的!加上冒号后,被测试的变量未被配置或者是已被配置为空字符串时, 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与配置

总结:

变量配置方式str 没有配置str 为空字符串str 已配置非为空字符串
var=${str-expr}var=exprvar=var=$str
var=${str:-expr}var=exprvar=exprvar=$str
var=${str+expr}var=var=exprvar=expr
var=${str:+expr}var=var=var=expr
var=${str=expr}str=expr
var=expr
str 不变
var=
str 不变
var=$str
var=${str:=expr}str=expr
var=expr
str=expr
var=expr
str 不变
var=$str
var=${str?expr}expr 输出至 stderrvar=var=$str
var=${str:?expr}expr 输出至 stderrexpr 输出至 stderrvar=$str
测试:先假设 str 不存在 (用 unset) ,然后测试一下减号 (-) 的用法:
[root@www ~]# unset str; var=${str-newvar}
[root@www ~]# echo var="$var", str="$str"
var=newvar, str=        <==因为 str 不存在,所以 var 为 newvar

测试:若 str 已存在,测试一下 var 会变怎样?:
[root@www ~]# str="oldvar"; var=${str-newvar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar  <==因为 str 存在,所以 var 等于 str 的内容

这个减号的测试并不会影响到旧变量的内容, 如果想要将旧变量内容也一起替换掉的话,就使用等号 (=)

测试:先假设 str 不存在 (用 unset) ,然后测试一下等号 (=) 的用法:
[root@www ~]# unset str; var=${str=newvar}
[root@www ~]# echo var="$var", str="$str"
var=newvar, str=newvar  <==因为 str 不存在,所以 var/str 均为 newvar

测试:如果 str 已存在了,测试一下 var 会变怎样
[root@www ~]# str="oldvar"; var=${str=newvar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar  <==因为 str 存在,所以 var 等于 str 的内容

如果旧变量不存在时,整个测试就告知我『有错误』,此时就能够使用问号『 ? 』的帮忙

测试:若 str 不存在时,则 var 的测试结果直接显示 "无此变量"
[root@www ~]# unset str; var=${str?无此变量}
-bash: str: 无此变量    <==因为 str 不存在,所以输出错误信息 

测试:若 str 存在时,则 var 的内容会与 str 相同!
[root@www ~]# str="oldvar"; var=${str?novar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar  <==因为 str 存在,所以 var 等于 str 的内容