嵌入式开发交流网论坛

标题: Linux的一些知识和简单的shell脚本编程 [打印本页]

作者: Rye丶哎呦    时间: 2020-12-15 11:06
标题: Linux的一些知识和简单的shell脚本编程
Linux的系统自带的头文件,或者用apt-get命令安装的头文件,一般在/usr/include目录,.a和.so库文件则在/usr/lib目录,可执行文件在/usr/bin目录。
如果自己编译安装的库,头文件在/usr/local/include,库文件在/usr/local/lib,可执行文件在/usr/local/bin。
下图就是/usr/local/lib和/usr/local/include目录,可以看到有解析json格式的cjson库,http协议的常用客户端curl使用的libcurl库,还有libhiredis.a,它就是redis数据库的客户端使用的库(nginx和redis异步接口对接的那篇文章,用的就是它),还有一堆opencv的库,它是个c++写的计算机视觉的开源项目。
[attach]55746[/attach]
Linux的可执行文件,在编译的时候可以使用动态连接,也可以使用静态连接。
动态连接:gcc -g -O3 -fpic -shared sample.c -lcjson -L/usr/local/lib
静态连接:gcc -g -O3 -static sample.c -lcjson -L/usr/local/lib
静态连接在编译完之后不再依赖所需的库,库函数的代码直接拷贝到可执行程序里,当然程序的大小也会较大。
动态连接的可执行程序较小,但需要依赖所需的动态库。如果动态库的路径不对,就会出现找不到库而无法执行的情况。查看某个可执行文件依赖的动态库,使用ldd命令,见下图。
动态库的查找,依赖当前用户的LD_LIBRARY_PATH环境变量,它要包含所需的库所在的目录才行。
[attach]55747[/attach]
可以在用户的~/.bashrc文件里配置这个环境变量,这样用户登陆时就会初始化对应的环境变量。Linux的~代表当前用户的home目录,实际指向/home/user目录,user要改为相应的用户名。
在这个文件的系统自带的内容之后(17行的fi之后),文件的尾部,可以添加自己的配置。
导出环境变量用export命令,一定要在系统自带的配置项的基础上添加,而不是直接修改,以防覆盖了系统原有的配置导致出错。
export PATH=$PATH:/usr/local/cuda/bin
$PATH表示引用系统自带的配置,每一项之间用:分割,这个配置的是CUDA的路径,CUDA默认安装在/usr/local/cuda/目录下。
PATH环境变量是可执行文件的路径,LD_LIBRARY_PATH是动态库的路径。
[attach]55748[/attach]
上古时代的内存和磁盘空间比较金贵,所以想尽各种办法节省空间,才有的动态库。例如2000年的一般内存配置是64-256M,硬盘20-40G,谁有个512M内存+80G硬盘就算高配置。
更扯淡的是,那时候没有U盘,只能用软盘携带资料,软盘大小1.44M(笑哭
动态库导致了不少的笑话,例如测试机器和目标机器的动态库版本不一样,程序跑不起来了,查了各种可能最后看了看动态库的md5不一样(尴尬
所以,新出的go语言去掉了动态库。
最后用个例子简单说一下linux常用命令和shell编程。
ls,列目录,后面可以跟目录的路径,默认当前目录。简单的就直接ls,需要看文件的大小和权限就用ls -al。
pwd,打印当前目录,没有参数。
chmod,修改文件权限。
一般常用的就是chmod +x run.sh,为shell脚本增加执行权限。
或者 chmod 0666 doc.txt,为doc.txt设置读写权限。
或者干脆chmod 0777 doc.txt,打开全部的权限,虽然对文本文件的执行权限没意义。r表示读,w表示写,x表示执行。
cd,进入一个目录,后面跟目的目录的绝对路径,或者相对路径。
ps,查看进程,一般是ps -ef | grep nginx,或者ps -aux | grep nginx,查看nginx的进程存不存在。如果查看其他程序的,则把nginx替换为相应的名字。
top,查看CPU和内存的消耗,消耗大的进程排前面。
ifconfig,查看网络情况。
kill,给进程发信号,kill -9 pid,杀进程,pid为进程号。也可以用pkill -9 nginx,pkill可以用进程的文件名,功能与kill一样。
cat,打印文件内容,后面直接跟文件的路径,当前路径则直接文件名。
gdb,调试可执行程序是gdb run,如果是查看core文件则是gdb run core,然后进入gdb的工作界面。
wc -l,统计文件的行数,后跟文件名。
grep,查找字符串,查找当前目录下的文件里的字符串用grep -r ngx_http_block,查找哪个文件的那一行有ngx_http_block函数,一般用于搜索代码。
find . -name 文件名,用于在当前目录下搜索相关的文件。
最后,我们写个简单的shell脚本,提取http的返回码,正文字节数,正文类型。
[attach]55749[/attach]
上图是curl -I 获得的http返回头,第1行中间的那个200就是返回码,第5行Content-Length项就是正文的字节数,第6行Content-Type为正文的类型,这里是html文件。
shell文件的第1行加#!/bin/bash ,表示用bash解释这个脚本。
第3行获取http返回码,并把它存到变量HTTP_CODE里。
shell也是弱类型语言,不需要提前声明变量。
``这个符号扩起来的部分为linux命令,可以把命令的返回结果赋值给=左边的变量,`位于键盘的数字1的左边,Tab的上边,与~在同一个键上,不是引号。
sed和gawk,是shell脚本里常用的字符串处理命令。
$1,表示shell脚本的命令行参数,命令行参数的0号是可执行文件本身的名字,1号为第一个参数,与C语言的main函数的参数类似,我们把前面的那个http头的文件作为参数输入进来。
sed的-n参数表示不打印源文件,只打印处理的结果,-e表示后面跟sed的处理命令,用单引号''扩起来的字符串,1p表示打印第一行,1是行号,p是print。
|是管道符号,代码里的进程通信使用socketpair了,shell命令里还是使用管道。
管道符号|之前的sed命令是打印文件的第1行,即打印HTTP/1.1 200 OK,通过管道把这行字符串传递给gawk,然后gawk以空格作为分割符打印第2个元素,即返回码200。gawk的处理命令也是单引号的字符串,只是多了个{}扩起来。
第4行的echo命令,输出获取的HTTP_CODE的值,shell引用变量时要加$符号,定义时不用。
第6行为获取http头的行数,使用了wc -l 命令,它的结果是:行数 文件名,这2项之间以空格分开,所以gawk打印第1项就是行数,把它存在LINES变量里。
第9行为for循环,shell支持C风格的for循环,只是要改为两个括号(),使用do和done表示循环体的开始和结束,而不是大括号{}。
这里从第2行开始,遍历所有的行,查找Content-Length和Content-Type这两项。
行号是用来组合sed命令的,所以按sed的规则从1开始,第1行是http返回码,所以从第2行开始查找,http头的其他部分都是以冒号:分开的键值对。
$i'p',这么并在一起,就能组合成行号p的sed命令,它是一个字符串,我们把sed返回的每一行存在TEXT变量里。
echo把TEXT的内容传递给gawk,第1个元素为键,第2个为值,以冒号分割,所以gawk的分割符要用-F:设置为冒号。
用if比较KEY是不是Content-Length或者Content-Type,如果是则打印对应的VAL。
shell里用==比较字符串相等,用-eq比较数字相等,它们与表示条件表达式的之间前后各有一个空格,不能连在一起。
[attach]55750[/attach]
效果图:
[attach]55751[/attach]




欢迎光临 嵌入式开发交流网论坛 (http://www.dianzixuexi.com/bbs/) Powered by Discuz! X3.2