初识Shell语言之系统命令基础

初识Shell语言之系统命令基础

2 年前 · 来自专栏 Linux基础

初识Shell之系统命令基础

一、Shell介绍

Shell 中文意思贝壳,寓意类似内核的壳。是指“为使用者提供操作界面”的软件(命令解析器),shell是你(用户)和Linux(或者更准确的说,是你和Linux内核)之间的接口程序。
你在提示符下输入的每个命令都由shell先解释然后传给Linux内核。这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务,简而言之就是只要能够操作应用程序的接口都能够称为SHELL。
# 什么是Shell
shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动、挂起、停止甚至是编写一些程序。
shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。shell是解释执行的脚本语言,在shell中可以直接条用Linux系统命令


解释这个图的工作流程: 
  最底层是硬件,是通过内核来管理这个硬件,在外层应用程序或者敲入命令,内核是不能识别的,计算机只能识别机器语言,所有命令和内核需要相互转换,命令转换为机器语言,把返回的结果从机器语言,翻译成命令,那谁来处理这个事情那??? 
  答案是shell来做,最主要的工作是把敲入的命令,翻译成内核可以识别的机器语言,然后这个内核才可以按照我们的要求来调用硬件来完成操作, 操作完成之后,这个硬件会把执行结果返回给内核,内核也需要通过shell,把机器语言翻译成我们看懂的语言,然后再呈现给用户。
  Shell就是交互界面, 所在终端操作的这个界面,其实就是Linux的shell,没有shell根本就没办法区输入命令,及时打入了命令,系统也不能识别。
  Shell就是我们和计算机我们和内核之间进行交互的界面,最主要的功能就是让我有个地方可以输入命令。把我的命令翻译成计算机内核可以识别的机器语言,把这个命令传递给硬件,硬件来执行,当内核执行完成之后把他翻译成用户可以识别的语言。
  shell除了交互界面之外,还有另一个功能。这个是解释执行的脚本语言,不需要先单独进行编译,而是命令再执行过程当中,自动来进行编译。
  Shell之所以可以方便的帮助用户进行系统管理,最主要的原因是可以直接调用Linux系统命令。
  Windows有shell吗??? 为什么点击开始会弹出开始菜单???其实就是再windows再检测开始图标的范围之内,侦测到了单机左键的动作,就会调用这个程序,这个Windows的图形界面就是Windows的shell,在windows里不这样叫,Windows里面叫图形交互界面。

1.1)命令解释器

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
  所以说,shell可以指代两层意思:
  python语言 《==================》shell命令
  python解释器《=================》shell解释器
  操作系统《=====================》操作系统
  计算机硬件《===================》计算机硬件
sh(Bourne Shell)是一个早期的重要shell,1978年由史蒂夫·伯恩编写,并同Version 7 Unix一起发布。
bash(Bourne-Again Shell)是一个为GNU计划编写的Unix shell。1987年由布莱恩·福克斯创造。主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,是各种Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash的符号链接。
dash (Debian Almquist shell)一种 Unix shell。它比 Bash 小,只需要较少的磁盘空间,但是它的对话性功能也较少。它由 NetBSD版本的Almquist shell (ash)发展而来,于1997年由赫伯特·许(Herbert Xu)移植到Linux上,于2002年改名为 dash。
# sh 遵循POSIX规范:“当某行代码出错时,不继续往下解释”。bash 就算出错,也会继续向下执行。
# sh 跟bash的区别,实际上是bash有没开启POSIX模式的区别。
# 简单说,sh是bash的一种特殊的模式,sh就是开启了POSIX标准的bash, /bin/sh 相当于 /bin/bash --posix。
# 在Linux系统上/bin/sh往往是指向/bin/bash的符号链接
# ln -s /bin/bash /bin/sh
我们可以SHELL实现对Linux系统的管理例如:
1. 文件管理
2. 用户与权限管理
3. 进程管理
4. 磁盘管理
5. 网络管理
6. 软件管理

Posix(可移植操作系统接口)模式

# 一:简单来说:
POSIX(Portable Operating System Interface,可移植操作系统接口),是操作系统为应用程序提供的接口标准。
简单的说, POSIX(主要是解决了应用程序在各个操作系统上兼容性这样一个普遍存在的问题。只要一个应用程序的开发是为了在一个实现了POSIX模式的操作系统上运行,那么这个应用程序就可以在所用实现了POSIX模式的操作系统上运行。
# 1、POSIX定义
POSIX: Portable Operating System Interface of Unix.,可移植操作系统接口。X表示其是对Unix API的传承。
POSIX标准由IEEE(电气和电子工程师协会)发布,定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种UNIX操作系统上运行软件而定义的一系列API标准的总称。
简单可以理解POSIX标准是为操作系统设计API时遵循的规范,一套规范的系统调用集。
# 2、POSIX的诞生/解决的问题
POSIX的诞生和Unix的发展是密不可分的。当年最早的Unix,源代码流传出去了,加上早期的Unix不够完善,于是之后出现了好些独立开发的与Unix基本兼容但又不完全兼容的OS,通称Unix-like OS。这样版本混乱的情况导致相互之间的竞争和不兼容之处越来越多,给软件的可移植性带来很大困难,对Unix的发展极为不利。
为了提高兼容性和应用程序的可移植性,结束混乱局面,IEEE提出了POSIX标准,POSIX在源代码级别上定义了一组最小的Unix(类unix)操作系统接口。 这套标准涵盖了很多方面,比如Unix系统调用的C语言接口,shell程序和工具、线程和网络编程等。POSIX标准意在期望获得源代码级别的软件可移植性。为一个POSIX兼容的操作系统编写的程序,可以在任何其他POSIX操作系统上编译执行。
POSIX现在已经发展成为一个非常庞大的标准族,并不局限于Unix, 一些其他的操作系统,如Microsoft windows NT, Linux等都支持或者部分支持POSIX标准。
# 3、POSIX标准的思路
问题: 不同操作系统内核为同一功能提供的系统调用(函数)是不同的,例如创建进程,linux下是fork函数,windows下是createprocess函数,如果在Linux下写了一个程序用到了fork函数,要往windows上移植就得把源代码里面的fork通通改成createprocess,然后重新编译。
解决方法: 定义POSIX标准, linux和windows实现基于POSIX标准,提供同样的接口,例如定义创建进程的接口为posix_fork(示例名/非真实名字), 且linux和windows都把各自创建进程的调用封装成posix_fork,都声明在unistd.h里。 这样程序员编写应用时,只需包含unistd.h, 调用这个POSIX标准中定义的API接口: posix_fork函数,即可实现源代码级别的可移植。

1.2)shell脚本

Shell 脚本(shell script)是一种为 shell 编写的脚本程序。常说的shell通常都是指 shell 脚本,但shell和shell 脚本是两个不同的概念。通常说“shell编程”都是指 shell 脚本编程,不是指开发 shell 自身。

GNU bash

Bash(GNU Bourne-Again Shell)是许多Linux平台的内定Shell,事实上,还有许多传统UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等,Shell Script大致都类同,即命令大都通用。当您学会一种Shell以后,其它的Shell会很快就上手,大多数的时候,一个Shell Script通常可以在很多种Shell上使用。
bash是大多数Linux系统以及Mac OS X v10.4默认的shell,bash具有极强的可移植性,它能运行于大多数Unix风格的操作系统之上,甚至被移植到了Microsoft Windows上的Cygwin系统中,以实现windows的POSIX虚拟接口。此外,它也被DJGPP项目移植到了MS-DOS上。bash的命令语法是Bourne shell命令语法的超集。数量庞大的Bourne shell脚本大多不经修改即可以在bash中执行,只有那些引用了Bourne特殊变量或使用了Bourne的内置命令的脚本才需要修改。 
bash的命令语法很多来自Korn shell (ksh) 和 C shell (csh), 例如命令行编辑,命令历史,目录栈,$RANDOM$PPID 变量,以及POSIX的命令置换语法: $(...)。GNU bash作为一个交互式的shell,按下TAB键即可自动补全已部分输入的程序名,文件名,变量名等等。

二、shell交互式环境

# 登录用户后进入解释器bash的交互式环境,可以敲命令,交互式环境的命令提示符如下
[root@drew ~]#
[root@drew ~]$ 
root                  # 当前登陆的用户
@                     # 分隔符
drew                  # 主机名
~                     # 当前所在的路径
#                     # [#]号代表超级管理员(root)用户对应的命令行
$                     # [$]号代表普通用户对应的命令行
# 创建普通系统用户
[root@drew ~]# useradd sxj
# 交互式给sxj用户设置密码为123
[root@drew ~]# passwd sxj
Changing password for user sxj.
New password: 123
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 123
passwd: all authentication tokens updated successfully.
# 非交互式设置密码为123
[root@drew ~]# echo "123" | passwd --stdin sxj
Changing password for user sxj.
passwd: all authentication tokens updated successfully.

三、shell命令语法

语法是指格式
# shell语法的三部分:
-   1.命令:需要执行的操作(必选)
-   2.选项:如何具体执行操作 通常以(- -- +)开头(可选)
-   3.参数:具体操作的对象(可选)
# ps:unix认为命令运行完毕后没有提示便是最好的提示,即结果正确,linux继承unix的优良传统

例子1

# 单独输入命令
[root@drew ~]# ls
anaconda-ks.cfg
# 命令+参数
[root@drew ~]# ls /root
anaconda-ks.cfg
# 命令+选项+参数
[root@drew ~]# ls -l /root
total 4
-rw-------. 1 root root 1751 Nov 17 20:21 anaconda-ks.cfg

例子2

# 查看系统时间
[root@drew ~]# date
Wed Apr 14 17:11:15 CST 2021
# 查看系统年月日(没有时间)
[root@drew ~]# date +%F
2021-04-14
# 修改系统时间为17:11:00 (date命令代表时间 -s代表修改,当后面加上参数-s就等于修改时间)后面会具体讲
[root@drew ~]# date -s 17:11:00
Wed Apr 14 17:11:00 CST 2021
# 查看系统时间已经修改成功
[root@drew ~]# date
Wed Apr 14 17:11:10 CST 2021
# 修改系统年月日与时间 修改为2022年11月11日 11点11分11秒
[root@drew ~]# date -s "2022-11-11 11:11:11"
Fri Nov 11 11:11:11 CST 2022
# 查看是否修改成功
[root@drew ~]# date +"%Y-%m-%d %H:%M:%S"
2022-11-11 11:13:17

四、bash解释器特性

# 命令和文件自动补全<tab>键 注意:Tab键总是能补全命令和文件
[root@drew ~]# ls /etc/sysc
sysconfig/   sysctl.conf  sysctl.d/

4.1)快捷键

Ctrl+c   终止前台运行的程序
Ctrl+d   退出 等价exit
Ctrl+l    清屏 
Ctrl+a   光标移到命令行的最前端
Ctrl+e   光标移到命令行的后端
Ctrl+r   搜索历史命令,利用关键词
Alt+. 引用上一个命令的最后一个参数,等价于!$

4.2)历史命令

# 查看历史命令
[root@drew ~]# history 
# 清空历史命令
[root@drew ~]# history -c
# 历史命令保存文件的路径
[root@drew ~]# cat ~/.bash_history
# 历史命名默认保存1000条,可以修改/etc/profile中更改默认值的HISTSIZE=2000
[root@drew ~]# vim /etc/profile
HISTSIZE=2000
# 查找历史命令并运行
(1)光标上下键
(2)Ctrl+r                       #搜索历史命令(输入一段某条命令的关键字:必须是连续的)
(reverse-i-search)`ls': ls
[root@drew ~]# ls
anaconda-ks.cfg
(3)!11                      # 执行历史命令中第11条命令
[root@drew ~]# !11
anaconda-ks.cfg
(4)!字符串                 # 搜索历史命令中最近一个以xxxx字符开头的命令,例如!ser
[root@drew ~]# !l
anaconda-ks.cfg
(5)!$                       # 引用上一个命令的最后一个参数
[root@drew ~]# ls
anaconda-ks.cfg
[root@drew ~]# !$
anaconda-ks.cfg

4.3)别名

# 查看系统已有的别名
[root@drew ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
# 建立一个别名
[root@drew ~]# alias drew='ls /etc/sysconfig/network-scripts/'
[root@drew ~]# drew
ifcfg-eth0   ifdown-ippp    ifdown-sit       ifup-bnep  ifup-plusb   ifup-TeamPort
ifcfg-eth1   ifdown-ipv6    ifdown-Team      ifup-eth   ifup-post    ifup-tunnel
ifcfg-lo     ifdown-isdn    ifdown-TeamPort  ifup-ippp  ifup-ppp     ifup-wireless
ifdown       ifdown-post    ifdown-tunnel    ifup-ipv6  ifup-routes  init.ipv6-global
ifdown-bnep  ifdown-ppp     ifup             ifup-isdn  ifup-sit     network-functions
ifdown-eth   ifdown-routes  ifup-aliases     ifup-plip  ifup-Team    network-functions-ipv6
# 取消别名
[root@drew ~]# unalias drew

五、命令查找优先级

# bash shell 查找优先级顺序
(1)以路径(绝对路径、相对路径)开始路径,例如:/bin/ls 或cd /bin
(2)alias 别名
(3)compound commands 组合命令/复合命令 for、if、while 一堆命令的集合体
(4)function 函数 
(5)build_in内部命令如cd,kill,pwd,echo等,可以用"type -a命令"查看 #系统里面带的
(6)hash哈希  指的是命令执行后会缓存在hash哈希表中
(7)$PATH,环境变量,查看环境变量echo $PATH,例如/bin/ls #放置操作系统要用的命令(如果你要是有别的命令也是可以添加进去,下次执行的时候直接输入命令即可)

基础概念

linux命令是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命令类似。linux命令在系统中有两种类型:内部Shell命令和外部命令

内部命令

集成在bash的命令,就是内部命令。内部命令依赖于shell类型。这些命令由shell程序识别并在shell程序内部完成运行,通常在linux系统加载运行时shell就被加载并驻留在系统内存中。内部命令是写在bash源码里面的,其执行速度比外部命令快,因为解析内部命令shell不需要创建子进程

外部命令

外部命令是在bash之外额外安装的,在文件系统路径$PATH有对应的可执行程序文件,就是外部命令。在系统加载时并不随系统一起被加载到内存中,而是在需要时才将其调用内存

命令别名

在管理和维护Linux系统的过程中,将会使用到大量命令,有一些很长的命令或用法经常被用到,重复而频繁地输入某个很长命令或用法是不可取的。这时可以使用命令别名功能将这个过程简单化

hash

系统初始hash表为空,当外部命令执行时,默认会从PATH路径下寻找该命令,找到后会将这条命令的路径记录到hash表中,当再次使用该命令时,shell解释器首先会查看hash表,存在将执行之,如果不存在,将会去PATH路径下寻找。利用hash缓存表可大大提高命令的调用速率

Linux命令执行过程

1、当输入一个命令后,系统会先判断该命令是否是内部命令,如果是内部命令,则直接在内存当中读取运行。
2、系统初始hash表为空,当外部命令执行时,默认会从PATH路径下寻找该命令,找到后会将这条命令的路径记录到hash表中,当再次使用该命令时,shell解释器首先会查看hash表,存在将执行之,如果不存在,将会去PATH路径下寻找。利用hash缓存表可大大提高命令的调用速率

六、查看帮助信息

6.1)Man手册

# 1、简单使用
[root@drew ~]# man 命令
# 2、详解如下
[root@drew ~]# man ls
进入页面搜索:/-h选项      n N
技巧二:按关键字检索(适合记不住手册的全名时使用)
man -k "_selinux"         //手册名或手册描述中包含关键字_selinux
注:从whatis数据库里找(# makewhatis)
技巧三:在所有章节中查询
# man -a passwd
# man -f passwd

6.2)--help或者help命令

命令 --help
help 命令
[root@xxx ~]# ls --help
用法:ls [选项]... [文件]...
ls 常见选项
-a    all,查看目录下的所有文件,包括隐藏文件
-l     长列表显示
-h    human 以人性化方式显示出来   
-d    只列出目录名,不列出其他内容
-t     按修改时间排序
-r     逆序排列
-i      显示文件的inode号(索引号)
3、info 非常详细的显示命令的说明信息
4、官方手册
5、baidu, google
# linux命令详解网站
https://man.linuxde.net/

七、常用命令

设置主机名

# 退出重新进入即可看到
[root@iZm5e59rizbgmmp4net6zbZ ~]# hostnamectl set-hostname drew

设置默认启动级别

# 设置启动级别为图形界面
[root@drew ~]# systemctl set-default graphical.target
# 设置启动级别为字符终端
[root@drew ~]# systemctl set-default multi-user.target

查看ip地址

# 也可以执行ip address或者简写ip a
[root@drew ~]# ifconfig

设置时间

# 查看关于date命令的帮助
[root@aliyun ~]# date --help
[root@drew ~]# date "+%Y_%m_%d  %H-%M-%S"
2021_04_15  16-49-50
[root@drew ~]# date -s "2018-05-17 09:51:50"
# =============》date设置的是系统时间,实际上时间分为硬件时钟与系统时钟两种
#1、硬件时钟:硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟,硬件时间存放于CMOS中。
#2、系统时钟:系统时钟则是指kernel(核心)中的时钟,当Linux启动时
ps:硬件时间默认比系统时间慢8个小时
# =============》硬件时钟与系统时钟的关系是:
Linux操作系统将时间从CMOS(驱动程序)中读到系统时间变量中,之后系统时钟即独立运作。所有Linux相关指令与函数都是读取系统时钟的设定。
linux系统设置硬件时钟时,提供两种时区选择,一种为本地时区,此时硬件时间与系统时间相同;另一种为UTC时区,此时硬件时间存的是UTC时间,系统初始化时会转换为本地时间后再设置为系统时钟的时间。
(UTC 是协调世界时(Universal Time Coordinated)英文缩写,是由国际无线电咨询委员会规定和推荐,并由国际时间局(BIH)负责保持的以秒为基础的时间标度。UTC相当于本初子 午线(即经度0度)上的平均太阳时,过去曾用格林威治平均时(GMT)来表示.北京时间比UTC时间早8小时,以1999年1月1日0000UTC为 例,UTC时间是零点,北京时间为1999年1月1日早上8点整。)
以后修改时间通过修改系统时间实现。为了保持系统时间与CMOS时间的一致性,Linux每隔一段时间会将系统时间写入CMOS。由于该同步是每隔一段时间(大约是11分钟)进行的,在我们执行date -s后,如果马上重起机器,修改时间就有可能没有被写入CMOS,这就是问题的原因。
如果要确保修改生效可以执行如下命令。
#hwclock –w
这个命令强制把系统时间写入CMOS。
# =============》hwclock命令
hwclock命令,主要用来查询和设置硬件时钟(query and set the hardware clock (RTC))。RTC=Real Time Clock,也就是硬件时钟。在Linux中有硬件时钟与系统时钟等两种时钟。硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟。系统时钟则是指kernel中
的时钟。所有Linux相关指令与函数都是读取系统时钟的设定。因为存在两种不同的时钟,那么它们之间就会存在差异。根据不同参数设置,hwclock命令既可以将硬件时钟同步到系统时钟,也可以将系统时钟同步到硬件时钟。
# hwclock命令的参数
-r, --show 读取并打印硬件时钟
-s, --hctosys 将硬件时钟同步到系统时钟
-w, --systohc 将系统时钟同步到硬件时钟
# =============》时间服务器
注意:要使系统时间准确,最好还是使用ntp方式,即将Linux系统时钟同步到远程NTP服务器,ps:centos7用chrony替换ntp,此处暂作了解:https://www.cnblogs.com/linhaifeng/articles/13471989.html  
NTP即Network Time Protocol(网络时间协议),是一个互联网协议,用于同步计算机之间的系统时钟。timedatectl实用程序可以自动同步你的Linux系统时钟到使用NTP的远程服务器。
注意,你必须在系统上安装NTP以实现与NTP服务器的自动时间同步。
使用ntpdate命令从网络同步时间,再同步到硬件时钟
ntpdate命令是使用NTP协议来从网络同步时间的命令。NTP=Network Time Protocol 网络时间协议。
#系统中默认没有ntpdate命令,需要自行下载安装
[root@drew ~]# yum install ntpdate -y
# 与网络时间服务器同步时间
[root@drew ~]# ntpdate 0.cn.pool.ntp.org
12 Aug 21:04:14 ntpdate[10099]: step time server 203.107.6.88 offset -7826995.450514 sec
[root@drew ~]# date
[root@drew ~]# hwclock -w
# 注意:
1、必须有 root 权限才能在主机上运行这个命令。
2、如果NTP服务器守护程序在当前主机上运行,命令将拒绝ntpdate设置日期
3、让系统自动同步时间,只需添加一条定时任务即可,后期会介绍到
# ps: 阿里云提供了7个NTP时间服务器也就是Internet时间同步服务器地址
ntp1.aliyun.com
ntp2.aliyun.com
ntp3.aliyun.com
ntp4.aliyun.com
ntp5.aliyun.com
ntp6.aliyun.com
ntp7.aliyun.com
# 要开启自动时间同步到远程NTP服务器,在终端键入以下命令。
[root@drew ~]# timedatectl set-ntp true
# 要禁用NTP时间同步,在终端键入以下命令。
[root@drew ~]# timedatectl set-ntp false

重启时间失效

# 关闭默认的时间同步,然后再进行设置
[root@drew ~]# timedatectl set-ntp no

设置时区

# 查看当前在用的时区
[root@drew ~]# timedatectl status
# 列出可用时区
[root@drew ~]# timedatectl list-timezones

重启

shutdown -r 10           # 10分钟后重启
shutdown -r 0            # 立即重启
shutdown -r now          # 立即重启
shutdown -r 11:30        # 定时重启
init 6                   # 立即重启
reboot                   # 立即重启

关机

shutdown -h 10           # 10分钟后关机
shutdown -h 0            # 立刻关机