Linux常用命令总结

1、文件和目录:

# cd /home                        进入 '/home' 目录

# cd ..                                返回上一级目录

# cd ../..                            返回上两级目录

# cd -                                返回上次所在目录

# cp file1 file2                    将file1复制为file2

# cp -a dir1 dir2                复制一个目录

# cp -a /tmp/dir1 .              复制一个目录到当前工作目录(.代表当前目录)

# ls                                    查看目录中的文件

# ls -a                                显示隐藏文件

# ls -l                                显示详细信息

# ls -lrt                              按时间显示文件(l表示详细列表,r表示反向排序,t表示按时间排序)

# pwd                                显示工作路径

# mkdir dir1                      创建 'dir1' 目录

# mkdir dir1 dir2                同时创建两个目录

# mkdir -p /tmp/dir1/dir2    创建一个目录树

# mv dir1 dir2                    移动/重命名一个目录

# rm -f file1                        删除 'file1'

# rm -rf dir1                      删除 'dir1' 目录及其子目录内容

2、查看文件内容:

# cat file1                          从第一个字节开始正向查看文件的内容

# head -2 file1                  查看一个文件的前两行

# more file1                      查看一个长文件的内容

# tac file1                          从最后一行开始反向查看一个文件的内容

# tail -3 file1                      查看一个文件的最后三行

3、文本处理:

# grep str /tmp/test            在文件 '/tmp/test' 中查找 "str"

# grep ^str /tmp/test          在文件 '/tmp/test' 中查找以 "str" 开始的行

# grep [0-9] /tmp/test        查找 '/tmp/test' 文件中所有包含数字的行

# grep str -r /tmp/*            在目录 '/tmp' 及其子目录中查找 "str"

# diff file1 file2                  找出两个文件的不同处

# sdiff file1 file2                以对比的方式显示两个文件的不同

awk 命令,文本处理神器

# awk '{print $1, $4}' netstat.txt        打印出netstat.txt中的第一列和第四列

其中单引号中的被大括号括着的就是awk的语句,注意,其只能被单引号包含。

其中的$1..$n表示第几例。注:$0表示整个行。

#awk '{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}' netstat.txt    按格式输出各列,和C语言的printf差不多

https://coolshell.cn/articles/9070.html

4、查找:

# find / -name file1                                                从 '/' 开始进入根文件系统查找文件和目录

# find / -user user1                                                查找属于用户 'user1' 的文件和目录

# find /home/user1 -name \*.bin                       在目录 '/ home/user1' 中查找以 '.bin' 结尾的文件

# find /usr/bin -type f -atime +100                        查找在过去100天内未被使用过的执行文件

# find /usr/bin -type f -mtime -10                          查找在10天内被创建或者修改过的文件

# find -name \*.c | xargs grep -E 'expr'    在当前目录及其子目录所有.c结尾的文件中查找 'expr'

# find -name '*.[ch]' | xargs grep -E 'expr'      在当前目录及其子目录所有.c和.h文件中查找 'expr'

# find -type f -print0 | xargs -r0 grep -F 'expr'     在当前目录及其子目录的常规文件中查找 'expr'

# find -maxdepth 1 -type f | xargs grep -F 'expr'    在当前目录中查找 'expr'

# locate \*.ps                                                    寻找以 '.ps' 结尾的文件,先运行 'updatedb' 命令

locate(locate) 命令用来查找文件或目录。 locate命令要比find -name快得多,原因在于它不搜索具体目录,而是搜索一个数据库/var/lib/mlocate/mlocate.db 。这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次,因此,我们在用whereis和locate 查找文件时,有时会找到已经被删除的数据,或者刚刚建立文件,却无法查找到,原因就是因为数据库文件没有被更新。为了避免这种情况,可以在使用locate之前,先使用updatedb命令,手动更新数据库。整个locate工作其实是由四部分组成的:

/usr/bin/updatedb  主要用来更新数据库,通过crontab自动完成的

/usr/bin/locate        查询文件位置

/etc/updatedb.conf  updatedb的配置文件

/var/lib/mlocate/mlocate.db  存放文件信息的文件

whereis (whereis) 命令用来定位指令的二进制程序、源代码文件和man手册页等相关文件的路径。whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。

5、压缩和解压:

# bzip2 file1                                  压缩 file1

# bunzip2 file1.bz2                        解压 file1.bz2

# gzip file1                                    压缩 file1

# gzip -9 file1                                最大程度压缩 file1

# gunzip file1.gz                            解压 file1.gz

# tar -cvf archive.tar file1              把file1打包成 archive.tar

(-c: 建立压缩档案;-v: 显示所有过程;-f: 使用档案名字,是必须的,是最后一个参数;-x:解打包)

# tar -cvf archive.tar file1 dir1        把 file1,dir1 打包成 archive.tar

# tar -zcvf archive.tar.gz file1 dir1        把 file1,dir1 打包并压缩成 archive.tar.gz

# tar -tf archive.tar                        显示一个包中的内容

# tar -xvf archive.tar                      解打包

# tar -zxvf archive.tar                      先解压缩然后解打包

# tar -xvf archive.tar -C /tmp        把压缩包释放到 /tmp目录下

# zip file1.zip file1                          创建一个zip格式的压缩包

# zip -r file1.zip file1 dir1              把文件和目录压缩成一个zip格式的压缩包

# unzip file1.zip                            解压一个zip格式的压缩包到当前目录

# unzip test.zip -d /tmp/                解压一个zip格式的压缩包到 /tmp 目录

6、yum工具:

# yum -y install [package]              下载并安装一个rpm包,-y是自动选择yes确认是这个包要安装。不加-y还要手动确认

# yum local install [package.rpm]    安装一个rpm包,使用你自己的软件仓库解决所有依赖关系

# yum -y update                              更新当前系统中安装的所有rpm包

# yum update [package]                更新一个rpm包

# yum remove [package]                删除一个rpm包

# yum list                                        列出当前系统中安装的所有包

# yum search [package]                在rpm仓库中搜寻软件包

# yum clean [package]                  清除缓存目录(/var/cache/yum)下的软件包

# yum clean headers                      删除所有头文件

# yum clean all                                删除所有缓存的包和头文件

上面是centos操作系统。若是ubuntu操作系统,则用apt-get 命令代替yum命令来安装软件。

7、网络:

# ifconfig eth0                                                                      显示一个以太网卡的配置

# ifconfig eth0 192.168.1.1 netmask 255.255.255.0            配置网卡的IP地址

# ifdown eth0                                                                        禁用 'eth0' 网络设备

# ifup eth0                                                                            启用 'eth0' 网络设备

# iwconfig eth1                                                                    显示一个无线网卡的配置

# iwlist scan                                                                        显示无线网络

# ip addr show                                                                    显示网卡的IP地址

8、其他:

# su -                                切换到root权限(与# su有区别)su与su -命令是有着本质区别

(前者只是切换了root身份,但Shell环境仍然是普通用户的Shell;而后者连用户和Shell环境一起切换成root身份了。只有切换了Shell环境才不会出现PATH环境变量错误。su切换成root用户以后,pwd一下,发现工作目录仍然是普通用户的工作目录;而用su -命令切换以后,工作目录变成root的工作目录了。)

# shutdown -h now          关机

# shutdown -r now            重启

# top                                  罗列使用CPU资源最多的linux任务 (输入q或者快捷键ctrl+c退出)

#iostat        (I/O statistics 输入/输出统计) 命令对系统的磁盘操作活动进行监视。它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况

# pstree                            以树状图显示程序

# man ping                        查看manual参考手册(例如ping 命令)

# passwd                          修改密码

# df -h                              disk free显示磁盘的使用情况

#du -ah [目录/文件]         (Disk usage) 用来计算每个文件的磁盘用量,目录则取总用量。省略目录/文件,则是当前文件。参数-a是指all所有文件,-h是指human即按照人性化的方式显示文件大小(单位K,M,G) 

# cal -3                            显示前一个月,当前月以及下一个月的月历

# cal 10 1988                  显示指定月,年的月历

# date --date '1970-01-01 UTC 1427888888 seconds'  把一相对于1970-01-01 00:00的秒数转换成时间

#link 源文件名 目标文件名        (link也可省略为ln)硬链接,inode文件唯一标识符不变,内存不变,只是多一个文件名(便于人阅读的文件名,实际linux系统中都是使用inode号去指向一块内存来保存文件数据)。

#link -s 原文件名 目标文件名     软链接,会新增一个inode,只是指向的内存数据是保存的原inode,相当于windows下的一个快捷方式。

#ls -i        i表示inode,表示列出当前目录下所有文件的inode号

cp命令会新增inode号,mv命令不新增inode号,rm命令先删除文件名减少链接数目,当链接数目=0时再清空内存块数据并释放inode号给系统用于下一次指向新的文件。

9.1、输出重定向

把其他命令运行后本应该打印显示在屏幕上的内容,保存到指定的文件中去,不显示在屏幕上。

(1)标准输出重定向,只在命令执行正确后保存运行结果到文件中

            #ifconfig > test.log        (创建新文件或者完全覆盖旧文件)

            #ifconfig >> test.log        (不覆盖内容,会在后面追加内容)

(2)命令运行错误时保存到文件

            #命令 2> error.log   (或者追加内容 #命令 2>> error.log)

(3)正确和错误的都保存到文件

             #命令 &> test.log     (或者追加内容 #命令 &>> test.log)

  (4)如果命令正确运行输出到文件1,错误则输出到文件2

            #命令 > 文件1 2>文件2    (或者追加内容 #命令 >> 文件1 2>>文件2)

9.2、输入重定向

从文件或键盘输入字符串,作为前面命令执行需要的输入数据

# wc < 文件名        (wc命令,用于统计文件内字符行数[-l],单词数[-w],字符数。不加参数就是默认3个都统计)

# wc << 输入字符串 

9.3、管道符,多命令连接执行

(1)多命令顺序执行

        #命令1 ;命令2        (前面命令的输出不显示到屏幕上,只有最后一个命令的输出才显示)

(2)多命令依条件判断是否接着执行

        #命令1 && 命令2        (逻辑与,即命令1正确执行后才会执行命令2)

        #命令1  ||  命令2        (逻辑或,即命令1错误执行才会执行命令2)

        #命令 && echo yes  ||  echo no    (命令执行正确打印yes,错误执行打印no)

(3)管道符"|",命令的正确输出结果不打印显示到屏幕上,而是作为后面命令的输入

        #命令1 |  命令2        

        例如:

        #netstat -an | grep ESTABLISHED        (先查看所有的网络连接和端口使用情况,然后用grep命令筛选出现 ESTABLISHED字符串的那些行,也就是只显示已建立连接的TCP端口)

        #netstat -an | grep ESTABLISHED | wc -l        (再用wc命令统计出已连接的TCP端口数量,最后只在屏幕打印输出一个数字)

        #ps aux | grep freeswitch    或    #ps -ef | grep freeswitch (两者都会先列出所有的进程,然后打印出和freeswitch相关的进程,然后我们可以看到进程号pid,就可以轻松的根据pid来执行kill -9 pid号 结束进程)

PS的aux和-ef参数的区别

一直以为ps aux就可以列出所有的在运行进程,最近发现还是有些缺陷,用ps aux和-ef得到的结果居然不一样,以后尽量用-ef参数吧。

情况是这样的,我用/bmrt/blaph/blaph/bmgctl来启动进程,由于ps aux是用BSD格式来显示结果,所以可能只会显示到/bmrt/blaph/blap,后面的都被截掉了。

这样,如果用ps aux | grep bmgctl 来过滤该进程,可能就会误伤,获取不到bmgctl进程。

而ps -ef是用全格式的System V格式,显示出来就是带全路径的进程名,会显示出bmgctl,在ps -ef | grep bmgctl命令下就可以完整显示该进程了。

——也就是说,用ps -ef更安全,ps aux可能显示的一行内容太长而会截断字符串,导致grep查找不到匹配的字符串而出错。

常用快捷键:

      CentOS 6.4 带图形界面系统中可以通过系统->首选项->键盘快捷键来设置快捷键。例如可将运行终端的快捷键设为Ctrl+Alt+T。

Ctrl + u            删除光标之前到行首的字符

Ctrl + k            删除光标之前到行尾的字符

Ctrl + c            取消当前行输入的命令,相当于Ctrl + Break

Ctrl + a            光标移动到行首(ahead of line),相当于通常的Home键

Ctrl + e            光标移动到行尾(end of line)

Ctrl + f            光标向前(forward)移动一个字符位置

Ctrl + b            光标往回(backward)移动一个字符位置

Ctrl + l            清屏,相当于执行clear命令

Ctrl + r            显示:号提示,根据用户输入查找相关历史命令(reverse-i-search)

Ctrl + w          删除从光标位置前到当前所处单词(word)的开头

Ctrl + t            交换光标位置前的两个字符

Ctrl + y            粘贴最后一次被删除的单词

Ctrl + Alt + d  显示桌面

Alt + b            光标往回(backward)移动到前一个单词

Alt + d            删除从光标位置到当前所处单词的末尾

Alt + F2          运行

Alt + F4          关闭当前窗口

Alt + F9          最小化当前窗口

Alt + F10        最大化当前窗口

Alt + Tab        切换窗口

Alt +按住左键  移动窗口(或在最下面的任务栏滚动鼠标滑轮)

[鼠标中间键] 粘贴突出显示的文本。使用鼠标左键来选择文本。把光标指向想粘贴文本的地方。点击鼠标中间键来粘贴。

[Tab] 命令行自动补全。使用 shell 提示时可使用这一方式。键入命令或文件名的前几个字符,然后按 [Tab] 键,它会自动补全命令或显示匹配键入字符的所有命令。

在桌面或文件管理器中直接按 / 就可以输入位置,打开文件管理器。

快速搜索:在 vi 、vim或 Firefox 中直接按 / 即可进入搜索状态。

网站链接和图片可直接拖放到桌面或者目录,可以马上下载。

直接将文件管理器中的文件拖到终端中就可以在终端中得到完整的路径名。

在滚动条的空白处点击鼠标中键,屏幕即滚动到那个地方。

10、杀死进程或者占用某个端口的进程

1、查找某个端口(比如8888)被哪个程序的进程占用。lsof(list open files)是一个列出当前系统打开文件的工具,需要root权限。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。lsof 常见的用法是查找应用程序打开的文件的名称和数目。可用于查找出某个特定应用程序将日志数据记录到何处,或者正在跟踪某个问题。

[root@centos ~]# lsof -i:8888            lsof -i 用以显示符合条件的进程情况

COMMAND    PID USER  FD  TYPE DEVICE SIZE/OFF NODE NAME

freeswitch 4982 root  69u  IPv4  21544      0t0  UDP *:ddi-udp-1

freeswitch 4982 root  76u  IPv4  21545      0t0  TCP *:ddi-tcp-1 (LISTEN)

另一种方法:

[root@centos mod_esl_json]# netstat -tunlp | grep 8888

tcp        0      0 0.0.0.0:8888                0.0.0.0:*                  LISTEN      4982/freeswitch

udp        0      0 0.0.0.0:8888                0.0.0.0:*                              4982/freeswitch

另一个命令:(能看到某个端口的状态,不能看到进程号pid值)

[root@centos ~]# netstat -an |grep 8888

tcp        0      0 0.0.0.0:8888                0.0.0.0:*                  LISTEN

tcp        0      0 192.168.0.106:8888          192.168.0.108:15423        TIME_WAIT

tcp        0      0 192.168.0.106:8888          192.168.0.108:15441        ESTABLISHED

udp        0      0 0.0.0.0:8888                0.0.0.0:*

2、比如 先查看 httpd 程序的进程

ps aux |grep httpd

[root@moyea309 init.d]# ps aux |grep httpd

root      2091  0.0  0.1  5488  2832 ?        Ss  17:19  0:00 /web/apache//bin/httpd -k restart

daemon    2475  0.0  0.1 283220  2256 ?        Sl  17:45  0:00 /web/apache//bin/httpd -k restart

daemon    2476  0.0  0.1 283220  2260 ?        Sl  17:45  0:00 /web/apache//bin/httpd -k restart

daemon    2477  0.0  0.1 283220  2260 ?        Sl  17:45  0:00 /web/apache//bin/httpd -k restart

root      2738  0.0  0.0  5500  736 pts/0    S+  17:56  0:00 grep httpd

这个就是 apache 的所有进程

我们可以用  kill -9 加进程ID  如下

[root@moyea309 init.d]# kill -9 2091

[root@moyea309 init.d]# kill -9 2475

[root@moyea309 init.d]# kill -9 2476

[root@moyea309 init.d]# kill -9 2477

[root@moyea309 init.d]# ps aux |grep httpd

root      2740  0.0  0.0  5500  732 pts/0    S+  17:58  0:00 grep httpd

全部杀完了...  杀死进程方法有很多种,,,,,我这个 只是其中的一种

# killall (-9) NAME    可以根据程序NAME名字杀死进程,但名字必须完全匹配。(-9)可选

查看当前正在运行的snmp相关进程# ps –ef | grep snmp,然后可以杀死对应的进程。

11、修改环境变量

查看PATH:echo $PATH

以添加mongodb server为列

修改方法一:

export PATH=/usr/local/mongodb/bin:$PATH

//配置完后可以通过echo $PATH查看配置结果。

生效方法:立即生效

有效期限:临时改变,只能在当前的终端窗口中有效,当前窗口关闭后就会恢复原有的path配置

用户局限:仅对当前用户

修改方法二:

通过修改.bashrc文件:

vim ~/.bashrc

//在最后一行添上:

export PATH=/usr/local/mongodb/bin:$PATH

生效方法:(有以下两种)

1、关闭当前终端窗口,重新打开一个新终端窗口就能生效

2、输入“source ~/.bashrc”命令,立即生效

有效期限:永久有效

用户局限:仅对当前用户

修改方法三:

通过修改profile文件:

vim /etc/profile

/export PATH //找到设置PATH的行,添加(vim的“/”是搜索后面带的字符串的意思)

export PATH=/usr/local/mongodb/bin:$PATH

生效方法:系统重启

有效期限:永久有效

用户局限:对所有用户

修改方法四:

通过修改environment文件:

vim /etc/environment

在PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"中加入“:/usr/local/mongodb/bin”

生效方法:系统重启

有效期限:永久有效

用户局限:对所有用户

12、service命令相关

控制系统服务的实用工具,可以启动、停止、重新启动和关闭系统服务,还可以显示所有系统服务的当前状态。

# service --status-all    显示/etc/init.d/下所有服务的状态(该目录下每个脚本文件是一个服务auditd functions ip6tables killall netconsole network rdisc  rsyslog  saslauthd  sshd  udev-post  crond  halt  iptables  messagebus  netfs  postfix  restorecond  sandbox single svnserve)

# service 服务名 status/stop/start/restart    服务名就是脚本文件名

常用的有:iptables(防火墙)  network(网络设备)

# service iptables stop   关闭防火墙

# service network status        查看网络设备的状态

# service network stop/start/restart  关闭所有网络设备(断网)/打开网络设备联网/重新联网

13、Linux下添加开机自启动服务,使service xxx命令能直接执行

1.按一定的规则编写服务脚本,比如:myserviced

#!/bin/bash 

#chkconfig: 2345 80 05       

#description: myservice 

# “#”号后面的都是注释。第一行默认不能变

case $1 in 

start) 

    echo "myservice startup"        #将该行替换成你自己的服务启动命令 

    ;; 

stop) 

    echo "myservice stop"            #将该行替换成你自己服务的启动命令 

    ;; 

restart) 

    echo "myservice stop"               #... 

    echo "myservice startup"           #... 

    ;; 

*) 

    ;; 

esac 

命令解析:

# chkconfig: 2345 80 5

2345表示服务的运行级别,80代表Start的顺序,05代表Kill(Stop)的顺序;

# description: service_description    该服务的描述

2.将编写的脚本放到/etc/init.d/,将myserviced的访问权限加上“可执行”

chmod +x myserviced 

3.增加服务

chkconfig --add myserviced         如此,该服务就可以开机自启动了

4.启停服务

service myserviced start 

service myserviced stop 

服务添加完成

可以用:chkconfig --list查看当前系统的服务

可以用:chkconfig --del myserviced删除服务

14、使用rpm包安装程序

如安装gdb,先下载好gdb的rpm包放到某个目录,然后运行:

rpm -ivh gdb-7.2-92.el6.x86_64.rpm

就安装gdb程序成功了。

15、shell脚本编写

1、$vim hello.sh            打开编辑脚本文件

        #!bin/bash                脚本文件开头必须写这一行

        脚本文件中每一行命令可以和在普通shell命令行敲的一样

2、退出vim编辑,保存脚本文件。

3、赋予脚本文件可执行权限

    #chmod 777 hello.sh            (777是所有用户都有权限执行,775是只有当前用户有权限执行)

4、执行脚本文件

    #./hello.sh        (当前文件夹,直接./执行,也可写全路径则可在任意目录下执行)

注:也可跳过3、4,直接用#bash hello.sh 直接执行(注意若不是当前目录则要用hello.sh的全路径)


16、使用gcc编译C语言源程序,g++编译C++源程序

(后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的。编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的(当然最好就用g++)。)


我们用gcc编译程序时,常常会用到“-I”(大写i),“-L”(大写l),“-l”(小写l)等参数,下面做个记录:例:

gcc -o hello hello1.c hello2.c hello3.c -I/home/hello/include -L/home/hello/lib -lworld

这条命令运行后,会在当前文件夹下产生一个hello文件,这个文件就是可执行文件(类似windows的hello.exe),在当前文件执行命令./hello,即可运行该文件,也就是运行后面三个C源文件。-o即out指定输出文件名。

上面这句表示在编译hello.c时:(如果有多个.c源文件联合编译,连着写就行。)

-I/home/hello/include,表示将/home/hello/include目录作为第一个寻找源代码中引入的头文件的目录,寻找的顺序是:/home/hello/include–>/usr/include–>/usr/local/include,也就是指定优先查找的目录,找不到的话查找默认目录。如果没有-I相关的指定,那么就是省略头文件位置默认为当前文件夹。

-L/home/hello/lib,表示将/home/hello/lib目录作为第一个寻找库文件的目录, 寻找的顺序是:/home/hello/lib–>/lib–>/usr/lib–>/usr/local/lib,同上,也是指定优先查找的目录,如果省略就是指当前文件夹优先。

-lword , 表示**寻找具体的动态链接库文件**libword.so(也就是文件名去掉前缀和后缀所代表的库文件),如果加上编译选项-static,表示寻找静态链接库文件,也就是libword.a。

当然也可以直接把连接库文件的全路径放过来,比如用/home/hello/lib/libword.a来代替-L/home/hello/lib -lworld。

当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然 而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。

对于第三方提供的动态链接库(.so),一般将其拷贝到一个lib目录下(/usr/local/lib),或者使用-L来指定其所在目录, 然后使用-l来指定其具体名称。

 现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数 void sayhello(); 另外还有一些说明文档。

这一个典型的程序开发包结构 与动态库连接, linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数

int main()

{

sayhello();

return 0;

}

使用如下命令进行编译 $gcc -c testlib.c     ,在当前文件夹得到链接文件testlib.o,无论静态库.a,还是动态库.so,都是由.o文件创建的。

再用如下命令连接: $gcc -o test testlib.o -lhello        ,在当前文件夹得到可执行文件test。

上面两步可以一步到位:$gcc -o test testlib.c -lhello        (libhello.so动态库文件放在当前目录)

https://www.cnblogs.com/yaozhongxiao/archive/2012/03/16/2400473.html

查看详细介绍如何用.o文件创建静态库.a和动态库.so文件。

17、gdb调试C/C++程序方法

一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如: 

$ gcc -g hello.c -o hello 

$ g++ -g hello.cpp -o hello 

如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。 

启动GDB的方法有以下几种:

1、$gdb program

program也就是你的执行文件,如上面的hello,一般在当然目录下。 

2、$gdb core 

用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。 

(在命令行运行这些命令后,启动gdb后,就你被带入gdb的调试环境中,就可以使用gdb的命令开始调试程序了)

详情举例见:https://blog.csdn.net/dadalan/article/details/3758025

一个调试示例 

—————— 

源程序:tst.c 

1 #include 

3 int func(int n) 

4 { 

5 int sum=0,i; 

6 for(i=0; i<7; i++) {

8 sum+=i; 

9 } 

10 return sum; 

11 } 

12 

13 

14 main() 

15 { 

16 int i; 

17 long result = 0; 

18 for(i=1; i<=100; i++) 

19 { 

20 result += i; 

21 } 

22 

23 printf("result[1-100] = %d /n", result ); 

24 printf("result[1-250] = %d /n", func(250) ); 

25 } 

编译生成执行文件:(Linux下) 

hchen/test$ gcc -g tst.c -o tst 

使用GDB调试: 

hchen/test$ gdb tst <---------- 启动GDB 

GNU gdb 5.1.1 

Copyright 2002 Free Software Foundation, Inc. 

GDB is free software, covered by the GNU General Public License, and you are 

welcome to change it and/or distribute copies of it under certain conditions. 

Type "show copying" to see the conditions. 

There is absolutely no warranty for GDB. Type "show warranty" for details. 

This GDB was configured as "i386-suse-linux"... 

(gdb) l <-------------------- l命令相当于list,从第一行开始例出原码。 

1 #include 

3 int func(int n) 

4 { 

5 int sum=0,i; 

6 for(i=0; i 7 { 

8 sum+=i; 

9 } 

10 return sum; 

(gdb) <-------------------- 直接回车表示,重复上一次命令 

11 }

12 

13 

14 main() 

15 { 

16 int i; 

17 long result = 0; 

18 for(i=1; i<=100; i++) 

19 { 

20 result += i; 

(gdb) break 16 <-------------------- 设置断点,在源程序第16行处。break命令也可简写成b 

Breakpoint 1 at 0x8048496: file tst.c, line 16. 

(gdb) break func <-------------------- 设置断点,在函数func()入口处。 

Breakpoint 2 at 0x8048456: file tst.c, line 5. 

(gdb) info break <-------------------- 查看断点信息。 

Num Type Disp Enb Address What 

1 breakpoint keep y 0x08048496 in main at tst.c:16 

2 breakpoint keep y 0x08048456 in func at tst.c:5 

(gdb) r <--------------------- 运行程序,run命令简写 

Starting program: /home/hchen/test/tst 

Breakpoint 1, main () at tst.c:17 <---------- 在断点处停住。 

17 long result = 0; 

(gdb) n <--------------------- 单条语句执行,next命令简写。 

18 for(i=1; i<=100; i++) 

(gdb)

20 result += i; 

(gdb)

18 for(i=1; i<=100; i++) 

(gdb)

20 result += i; 

(gdb) c <--------------------- 继续运行程序,continue命令简写。 

Continuing. 

result[1-100] = 5050 <----------程序输出。 

Breakpoint 2, func (n=250) at tst.c:5 

5 int sum=0,i; 

(gdb)

6 for(i=1; i<=n; i++) 

(gdb) p i <--------------------- 打印变量i的值,print命令简写。 

$1 = 134513808 

(gdb)

8 sum+=i; 

(gdb)

6 for(i=1; i<=n; i++)

(gdb) p sum 

$2 = 1 

(gdb) n 

8 sum+=i; 

(gdb) p i 

$3 = 2 

(gdb) n 

6 for(i=1; i<=n; i++) 

(gdb) p sum 

$4 = 3 

(gdb) bt <--------------------- 查看函数堆栈。 

#0 func (n=250) at tst.c:5 

#1 0x080484e4 in main () at tst.c:24 

#2 0x400409ed in __libc_start_main () from /lib/libc.so.6 

(gdb) finish <--------------------- 退出函数。 

Run till exit from #0 func (n=250) at tst.c:5 

0x080484e4 in main () at tst.c:24 

24 printf("result[1-250] = %d /n", func(250) ); 

Value returned is $6 = 31375 

(gdb) c <--------------------- 继续运行。 

Continuing. 

result[1-250] = 31375 <----------程序输出。 

Program exited with code 027. <--------程序退出,调试结束。 

(gdb) q <--------------------- quit,退出gdb。 

hchen/test$    回到linux命令行

以上示例展示了:进入gdb调试环境方式gcc -g,加断点命令break,开始执行命令run,单步执行next,继续连续执行命令continue,打印变量命令print,退出函数命令finish,退出gdb调试环境命令quit。

gcc -g main.c -o main            //把调试信息加到可执行文件中

gdb main                //进入gdb调试环境

(gdb) start                        //开始调试

(gdb) n                            //一条一条执行

(gdb) step/s                        //执行下一条,如果函数进入函数

(gdb) backtrace/bt                  //查看函数调用栈帧

(gdb) info/i locals                //查看当前栈帧局部变量

(gdb) frame/f                      //选择栈帧,再查看局部变量

(gdb) print/p                      //打印变量的值

(gdb) finish                        //运行到当前函数返回

(gdb) set var sum=0                //修改变量值

(gdb) list/l 行号或函数名            //列出源码

(gdb) display/undisplay sum        //每次停下显示变量的值/取消跟踪

(gdb) break/b  行号或函数名          //设置断点

(gdb) continue/c                    //连续运行

(gdb) info/i breakpoints            //查看已经设置的断点

(gdb) delete breakpoints 2          //删除某个断点

(gdb) disable/enable breakpoints 3  //禁用/启用某个断点

(gdb) break 9 if sum != 0          //满足条件才激活断点

(gdb) run/r                        //重新从程序开头连续执行

(gdb) watch input[4]                //设置观察点

(gdb) info/i watchpoints            //查看设置的观察点

(gdb) x/7b input                    //打印存储器内容,b--每个字节一组,7--7组

(gdb) disassemble                  //反汇编当前函数或指定函数

(gdb) si                            // 一条指令一条指令调试 而 s 是一行一行代码

(gdb) info registers                // 显示所有寄存器的当前值

(gdb) x/20 $esp                    //查看内存中开始的20个数