一、了解Linux目录配置标准FHS
FHS本质:是一套规定Linux目录结构,软件建议安装位置的标准。
(使用Linux来开发产品或者发布软件的公司、个人太多,如果每家公司或者个人都按照自己的意愿来配置文件或者软件的存放位置,这无疑是一场灾难 ! )
# 进入根目录 [root@localhost home]# cd / # 下载tree命令:以树状图查看目录结构 [root@localhost ~]# yum install -y tree # 查看目录树: # tree -d -L 1 用于以树状图的形式显示指定目录下的内容。 # 其中,-d 选项表示只显示目录名称,而不显示目录内容;-L 1选项表示只显示第一层目录。 [root@localhost /]# tree -d -L 1 . ├── bin -> usr/bin #可执行文件目录,linux自带命令在这里 ├── boot #开机会使用到的文件,包括Linux核心文件以及开机菜单与开机所需配置文件等等。 ├── dev #设备目录 ├── etc #配置文件几乎都放置在这个目录内,例如人员的帐号密码档、 各种服务的启始档等等。 ├── home #家目录,系统默认的使用者主文件夹,用户的个人文件都可放在这里 ├── lib -> usr/lib #放置在开机时会用到的函数库,以及在/bin或/sbin下面的指令会调用的函数库 ├── lib64 -> usr/lib64 #与lib类似 ├── media #放置可移除的设备,包括软盘、光盘、DVD等等设备都暂时挂载于此。 ├── mnt #设备临时挂载目录 ├── opt #第三方协力软件放置的目录 ├── proc #是一个虚拟文件系统,放置内存中的数据,不占用硬盘空间 ├── root #系统管理员的主文件夹 ├── run #放置系统开机后所产生的各项信息 ├── sbin -> usr/sbin #里面包括了开机、修复、还原系统所需要的指令,root用户使用 ├── srv #service是一些网络服务启动之后,这些服务所需要取用的数据目录。 ├── sys #与proc类似 ├── tmp #temp,让一般使用者或者是正在执行的程序暂时放置文件的地方 ├── usr #unix software resource:与软件安装/执行有关 └── var #variable,与系统运行过程有关,主要为变动性较大的数据 19 directories ————————————————
linux目录结构详细说明:linux目录结构详细说明
二、Linux数据重定向的理解与操作
2.1基本背景
基本大部分计算机,要与人交互,都要默认打开三个设备(文件)
- 标准输入,stdin,代码是0
- 标准错误,stdout,代码是1
- 标准错误输出,stderr,代码是2
为什么?Linux一切皆文件,交互需求,输入输出信息分类。除了上面的三个标准设备(文件), 我们可能经常有从文件读取数据,或者将数据写入文件的场景。
2.2重定向的理解
输出/追加重定向:本来应该显示到显示器(通常)文件的内容,写入到文件当中。
输入重定向:或者本来应该从显示器(通常)文件读取数据,转化成从指定文件读取数据
# 当前只有三个文件 [root@localhost Practice]# ls test2.txt test3.txt test.txt # 本来应该输出在控制台输出到了文件中 [root@localhost Practice]# echo 'Hello World' > test.txt [root@localhost Practice]# cat test.txt Hello World # 将'I am xx '输入到test.txt文件中,我们发现原来的内容被覆盖 [root@localhost Practice]# echo 'I am xx ' > test.txt [root@localhost Practice]# cat test.txt I am xx # 追加重定向:>> #将指定内容追加到文件内容的末尾 [root@localhost Practice]# echo 'Hello World' >> test.txt [root@localhost Practice]# cat test.txt I am xx Hello World
# 输入重定向:cat本来是查看文件内容 # 现在表示向test.txt中写数据 [root@localhost Practice]# cat > test.txt nihao #输入我们要写入的数据 #查看test.txt文件中的内容,发现之前的内容被nihao覆盖了 [root@localhost Practice]# cat test.txt nihao # 查看test2.txt文件的内容 [root@localhost Practice]# cat test2.txt Hello Linux # 理解:将test2.txt文件的内容写入test.txt文件 [root@localhost Practice]# cat < test2.txt > test.txt [root@localhost Practice]# cat test.txt Hello Linux
2.3Linux管道命令的理解与操作
命令是可以产生数据的,如果我们还要多输出数据进行加工,甚至想多次加工,就需要使用管道
[whb@VM-0-3-centos ~]$ last #显示正在或者最近登录linux的用户信息 whb pts/5 123.139.120.197 Tue Mar 2 16:24 still logged in wudu pts/4 222.91.65.7 Tue Mar 2 15:34 still logged in wudu pts/3 222.91.65.7 Tue Mar 2 15:34 still logged in whb pts/2 123.139.120.197 Tue Mar 2 15:21 still logged in root pts/1 222.91.65.7 Tue Mar 2 15:03 still logged in whb pts/0 123.139.120.197 Tue Mar 2 13:59 still logged in wudu pts/2 222.91.65.7 Tue Mar 2 12:12 - 13:52 (01:39) wudu pts/1 222.91.65.7 Tue Mar 2 12:12 - 13:52 (01:39) root pts/0 222.91.65.7 Tue Mar 2 12:12 - 13:52 (01:39) wudu pts/9 222.90.196.96 Mon Mar 1 14:48 - 01:38 (10:50) wudu pts/6 222.90.196.96 Mon Mar 1 14:41 - 01:38 (10:57) root pts/8 222.90.196.96 Mon Mar 1 14:19 - 01:39 (11:19) wudu pts/7 222.90.196.96 Mon Mar 1 14:16 - 01:39 (11:22) #如果我只想看到前5条信息呢? [whb@VM-0-3-centos ~]$ last | head -5 #其中'|'就是管道 #head是一个截取文本行的工具 whb pts/5 123.139.120.197 Tue Mar 2 16:24 still logged in wudu pts/4 222.91.65.7 Tue Mar 2 15:34 still logged in wudu pts/3 222.91.65.7 Tue Mar 2 15:34 still logged in whb pts/2 123.139.120.197 Tue Mar 2 15:21 still logged in root pts/1 222.91.65.7 Tue Mar 2 15:03 still logged in ...
可见,管道是可以级联多条命令的,每条命令的结果输出,都作为输入,导入下一条命令。有点像流水线.( | 前的内容作为输入,| 后的内容作为输出)
编辑
三、Linux 环境变量与PATH
假设我们想用C写一个输出 ‘hello world’ 的程序
[whb@VM-0-3-centos test]$ cat test.c #include <stdio.h> int main() { printf("hello world\n"); return 0; } # 编译文件gcc -o [whb@VM-0-3-centos test]$ gcc -o mycmd test.c [whb@VM-0-3-centos test]$ ll total 16 -rwxrwxr-x 1 whb whb 8400 Mar 2 16:46 mycmd -rw-rw-r-- 1 whb whb 74 Mar 2 16:46 test.c #等等,这个 './' 是什么东西?mycmd从构成上,也可以认为是一个命令 #像ls,就在/bin/ls or /usr/bin/ls, 为什么执行ls命令不需要带路径呢?(尽管也可以) [whb@VM-0-3-centos test]$ ./mycmd hello world
3.1环境变量PATH
是一个路径集,命令再被执行时,系统会在环境变量PATH中进行路径查找,如果找到,就停止查找,执行命令。
[whb@VM-0-3-centos test]$ echo $PATH #不同环境,平台可能内容会有不同 /usr/local/jdk8/bin:/usr/local/jdk8/jre/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sb in:/home/whb/.local/bin:/home/whb/bin $: 用来显示PATH环境变量的内容 #各个路径以 : 作为分隔符,每个区域代表一个搜索路径
这也就解释了,为何 ls 不需要带路径,因为 ls 所在的路径,本身就在PATH环境变量列表当中。
一条命令的执行过程:
1.找到
2.执行
当我们执行自己的命令时,需要加./,而系统命令不同,这是因为自己的命令系统找不到没有路径。在系统中,可执行程序的搜索路径保存在一个‘全局变量’PATH中(作用:给系统提供命令的搜索路径,是环境变量的一种)
查看'PATH的内容'--》相当于一个字符串:保存了多条路径,路径之间通过 :作为分隔符。采用从左向右依次进行程序搜索,找不到就搜索下一条路径,最终没有找到会报command not found的错误
# which 验证发现 ls 命令在系统的环境变量中存在 [whb@VM-0-3-centos test]$ which ls #which 显示指定命令所在路径 alias ls='ls --color=auto' /usr/bin/ls
那么问题来了,我也想让我的’hello world‘程序执行的时候不带‘./’这样的路径, 怎么办呢?
#方法一 [whb@VM-0-3-centos test]$ mycmd -bash: mycmd: command not found #将自己的命令随便拷贝到环境变量的路径中 [whb@VM-0-3-centos test]$ sudo cp mycmd /usr/bin [sudo] password for whb: [whb@VM-0-3-centos test]$ ls /usr/bin/mycmd /usr/bin/mycmd [whb@VM-0-3-centos test]$ mycmd #但是千万不要这样干,因为会‘污染’指令集 hello world #方法二 [whb@VM-0-3-centos test]$ echo $PATH /usr/local/jdk8/bin:/usr/local/jdk8/jre/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbi n:/home/whb/.local/bin:/home/whb/bin [whb@VM-0-3-centos test]$ pwd #查看自己当前处于哪个目录 /home/whb/test [whb@VM-0-3-centos test]$ export PATH=$PATH:/home/whb/test#导出新的环境变量,加上程序所在的路径 [whb@VM-0-3-centos test]$ echo $PATH /usr/local/jdk8/bin:/usr/local/jdk8/jre/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbi n:/home/whb/.local/bin:/home/whb/bin:/home/whb/test [whb@VM-0-3-centos test]$ sudo rm /usr/bin/mycmd #删掉在/usr/bin路径下的可执行程序 [whb@VM-0-3-centos test]$ which mycmd #mycmd已经能通过环境变量被找到 ~/test/mycmd [whb@VM-0-3-centos test]$ mycmd #可以不带路径 hello world
#了解一下即可 [whb@VM-0-3-centos test]$ env #显示当前用户环境变量 XDG_SESSION_ID=3288 HOSTNAME=VM-0-3-centos TERM=xterm SHELL=/bin/bash HISTSIZE=3000 SSH_CLIENT=123.139.120.197 21378 22 OLDPWD=/home/whb SSH_TTY=/dev/pts/6 JRE_HOME=/usr/local/jdk8/jre USER=whb LD_LIBRARY_PATH=:/home/whb/.VimForCpp/vim/bundle/YCM.so/el7.x86_64 CLASS_PATH=.:/usr/local/jdk8/lib LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or =40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.ta r=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31: *.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31: *.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01 ;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz =01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35: *.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=0 1;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:* .mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01 ;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fl i=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*. emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;3 6:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav= 01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36: MAIL=/var/spool/mail/whb PATH=/usr/local/jdk8/bin:/usr/local/jdk8/jre/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/us r/sbin:/home/whb/.local/bin:/home/whb/bin:/home/whb/test PWD=/home/whb/test JAVA_HOME=/usr/local/jdk8 LANG=en_US.utf8 SHLVL=1 HOME=/home/whb LOGNAME=whb SSH_CONNECTION=123.139.120.197 21378 172.17.0.3 22 LESSOPEN=||/usr/bin/lesspipe.sh %s PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" XDG_RUNTIME_DIR=/run/user/1005 HISTTIMEFORMAT=%F %T _=/usr/bin/env
系统本身会提供某种全局查找属性,帮我们找到特定的模块/程序
其实,编译器内部也有类似的功能,想想,为何我们#include<头文件> ,并没有指明头文件在哪里,但是编译器也能帮我们找到并展开,包括我们也并没有指明我们的程序依赖哪些第三方库,编译器也能找到。