HAPPY FAMILY¶
Tip
Write down whatever you want to write down! ^_^

This is level-2 title¶
This is level-2 title too¶Getting more info¶
批处理助记¶这部分笔记记录了平时工作中遇到的一些关于批处理文件编写的知识细节。 批处理教程¶该部分讲述windows批处理(cmd/bat)常用命令小结 前言¶批处理文件(batch file)包含一系列 DOS命令,通常用于自动执行重复性任务。用户只需双击批处理文件便可执行任务, 而无需重复输入相同指令。编写批处理文件非常简单,但难点在于确保一切按顺序执行。编写严谨的批处理文件可以 极大程度地节省时间,在应对重复性工作时尤其有效。 Important 在Windows中善用批处理可以简化很多重复工作 参考链接¶什么是批处理¶批处理(Batch),也称为批处理脚本。顾名思义,批处理就是对某对象进行批量的处理。批处理文件的扩展名为bat。 目前比较常见的批处理包含两类:DOS批处理和PS批处理。PS批处理是基于强大的图片编辑软件Photoshop的,用来批量处理图片的脚本; 而DOS批处理则是基于DOS命令的,用来自动地批量地执行DOS命令以实现特定操作的脚本。这里要讲的就是DOS批处理。 批处理是一种简化的脚本语言,它应用于DOS和Windows系统中,它是由DOS或者Windows系统内嵌的命令解释器(通常是COMMAND.COM或者CMD.EXE)解释运行。 类似于Unix中的Shell脚本。批处理文件具有.bat或者.cmd的扩展名,其最简单的例子,是逐行书写在命令行中会用到的各种命令。更复杂的情况, 需要使用if,for,goto等命令控制程序的运行过程,如同C,Basic等中高级语言一样。如果需要实现更复杂的应用,利用外部程序是必要的, 这包括系统本身提供的外部命令和第三方提供的工具或者软件。 批处理文件,或称为批处理程序,是由一条条的DOS命令组成的普通文本文件,可以用记事本直接编辑或用DOS命令创建,也可以用DOS下的 文本编辑器Edit.exe来编辑。在“命令提示”下键入批处理文件的名称,或者双击该批处理文件,系统就会调用Cmd.exe运行该批处理程序。一般情况下, 每条命令占据一行;当然也可以将多条命令用特定符号(如:&、&&、|、||等)分隔后写入同一行中;还有的情况就是像if、for等较高级的命令则要占据几行甚至几十几百行的空间。 系统在解释运行批处理程序时,首先扫描整个批处理程序,然后从第一行代码开始向下逐句执行所有的命令,直至程序结尾或遇见exit命令或出错意外退出。 批处理命令简介¶
http://xstarcd.github.io/wiki/windows/windows_cmd_summary_commands.html 批处理符号简介¶
http://xstarcd.github.io/wiki/windows/windows_cmd_summary_symbols.html 常用DOS命令¶文件夹管理
文件管理
网络命令
系统管理
Hint 对于以上列出的所有命令,在cmd中输入命令+/?即可查看该命令的帮助信息。如find /? Windows Batch 常用命令¶1 echo 和 @
回显命令
@ #关闭单行回显
echo off #从下一行开始关闭回显
@echo off #从本行开始关闭回显。一般批处理第一行都是这个
echo on #从下一行开始打开回显
echo #显示当前是 echo off 状态还是 echo on 状态
echo. #输出一个”回车换行”,空白行
#(同echo, echo; echo+ echo[ echo] echo/ echo)
2 errorlevel
echo %errorlevel%
每个命令运行结束,可以用这个命令行格式查看返回码
默认值为0,一般命令执行出错会设 errorlevel 为1
3 dir
显示文件夹内容
dir #显示当前目录中的文件和子目录
dir /a #显示当前目录中的文件和子目录,包括隐藏文件和系统文件
dir c: /a:d #显示 C 盘当前目录中的目录
dir c: /a:-d #显示 C 盘根目录中的文件
dir c: /b/p #/b只显示文件名,/p分页显示
dir *.exe /s #显示当前目录和子目录里所有的.exe文件
4 cd
切换目录
cd #进入根目录
cd #显示当前目录
cd /d d:sdk #可以同时更改盘符和目录
5 md
创建目录
md d:abc #如果 d:a 不存在,将会自动创建中级目录
#如果命令扩展名被停用,则需要键入 mkdir abc。
6 rd
删除目录
rd abc #删除当前目录里的 abc 子目录,要求为空目录
rd /s/q d:temp #删除 d:temp 文件夹及其子文件夹和文件,/q安静模式
7 del
删除文件
del d:test.txt #删除指定文件,不能是隐藏、系统、只读文件
del /q/a/f d:temp*.*
删除 d:temp 文件夹里面的所有文件,包括隐藏、只读、系统文件,不包括子目录
del /q/a/f/s d:temp*.*
删除 d:temp 及子文件夹里面的所有文件,包括隐藏、只读、系统文件,不包括子目录
8 ren
重命名命令
ren d:temp tmp #支持对文件夹的重命名
9 cls
清屏
10 type
显示文件内容
type c:boot.ini #显示指定文件的内容,程序文件一般会显示乱码
type *.txt #显示当前目录里所有.txt文件的内容
11 copy
拷贝文件
copy c:test.txt d:test.bak
复制 c:test.txt 文件到 d: ,并重命名为 test.bak
copy con test.txt
从屏幕上等待输入,按 Ctrl+Z 结束输入,输入内容存为test.txt文件
con代表屏幕,prn代表打印机,nul代表空设备
copy 1.txt + 2.txt 3.txt
合并 1.txt 和 2.txt 的内容,保存为 3.txt 文件
如果不指定 3.txt ,则保存到 1.txt
copy test.txt +
复制文件到自己,实际上是修改了文件日期
12 title
设置cmd窗口的标题
title 新标题 #可以看到cmd窗口的标题栏变了
13 ver
显示系统版本
14 label 和 vol
设置卷标
vol #显示卷标
label #显示卷标,同时提示输入新卷标
label c:system #设置C盘的卷标为 system
15 pause
暂停命令
16 rem 和 ::
注释命令
注释行不执行操作
17 date 和 time
日期和时间
date #显示当前日期,并提示输入新日期,按"回车"略过输入
date/t #只显示当前日期,不提示输入新日期
time #显示当前时间,并提示输入新时间,按"回车"略过输入
time/t #只显示当前时间,不提示输入新时间
18 goto 和 :
跳转命令
:label #行首为:表示该行是标签行,标签行不执行操作
goto label #跳转到指定的标签那一行
19 find (外部命令)
查找命令
find "abc" c:test.txt
在 c:test.txt 文件里查找含 abc 字符串的行
如果找不到,将设 errorlevel 返回码为1
find /i “abc” c:test.txt
查找含 abc 的行,忽略大小写
find /c "abc" c:test.txt
显示含 abc 的行的行数
20 more (外部命令)
逐屏显示
more c:test.txt #逐屏显示 c:test.txt 的文件内容
21 tree
显示目录结构
tree d: #显示D盘的文件目录结构
22 &
顺序执行多条命令,而不管命令是否执行成功
23 &&
顺序执行多条命令,当碰到执行出错的命令后将不执行后面的命令
find "ok" c:test.txt && echo 成功
如果找到了"ok"字样,就显示"成功",找不到就不显示
24 ||
顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令
find "ok" c:test.txt || echo 不成功
如果找不到"ok"字样,就显示"不成功",找到了就不显示
25 |
管道命令
dir *.* /s/a | find /c ".exe"
管道命令表示先执行 dir 命令,对其输出的结果执行后面的 find 命令
该命令行结果:输出当前文件夹及所有子文件夹里的.exe文件的个数
type c:test.txt|more
这个和 more c:test.txt 的效果是一样的
26 > 和 >>
输出重定向命令
> 清除文件中原有的内容后再写入
>> 追加内容到文件末尾,而不会清除原有的内容
主要将本来显示在屏幕上的内容输出到指定文件中
指定文件如果不存在,则自动生成该文件
type c:test.txt >prn
屏幕上不显示文件内容,转向输出到打印机
echo hello world>con
在屏幕上显示hello world,实际上所有输出都是默认 >con 的
copy c:test.txt f: >nul
拷贝文件,并且不显示"文件复制成功"的提示信息,但如果f盘不存在,还是会显示出错信息
copy c:test.txt f: >nul 2>nul
不显示”文件复制成功”的提示信息,并且f盘不存在的话,也不显示错误提示信息
echo ^^W ^> ^W>c:test.txt
生成的文件内容为 ^W > W
^ 和 > 是控制命令,要把它们输出到文件,必须在前面加个 ^ 符号
27 <
从文件中获得输入信息,而不是从屏幕上
一般用于 date time label 等需要等待输入的命令
@echo off
echo 2005-05-01>temp.txt
date <temp.txt
del temp.txt
这样就可以不等待输入直接修改当前日期
28 %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %*
命令行传递给批处理的参数
%0 批处理文件本身
%1 第一个参数
%9 第九个参数
%* 从第一个参数开始的所有参数
批参数(%n)的替代已被增强。您可以使用以下语法:
%~1 - 删除引号("),扩充 %1
%~f1 - 将 %1 扩充到一个完全合格的路径名
%~d1 - 仅将 %1 扩充到一个驱动器号
%~p1 - 仅将 %1 扩充到一个路径
%~n1 - 仅将 %1 扩充到一个文件名
%~x1 - 仅将 %1 扩充到一个文件扩展名
%~s1 - 扩充的路径指含有短名
%~a1 - 将 %1 扩充到文件属性
%~t1 - 将 %1 扩充到文件的日期/时间
%~z1 - 将 %1 扩充到文件的大小
%~$PATH : 1 - 查找列在 PATH 环境变量的目录,并将 %1
扩充到找到的第一个完全合格的名称。如果环境
变量名未被定义,或者没有找到文件,此组合键会
扩充到空字符串
可以组合修定符来取得多重结果:
%~dp1 - 只将 %1 扩展到驱动器号和路径
%~nx1 - 只将 %1 扩展到文件名和扩展名
%~dp$PATH:1 - 在列在 PATH 环境变量中的目录里查找 %1,
并扩展到找到的第一个文件的驱动器号和路径。
%~ftza1 - 将 %1 扩展到类似 DIR 的输出行。
可以参照 call/? 或 for/? 看出每个参数的含意
echo load "%%1" "%%2">c:test.txt
生成的文件内容为 load "%1" "%2"
批处理文件里,用这个格式把命令行参数输出到文件
29 if
判断命令
if "%1"=="/a" echo 第一个参数是/a
if /i "%1" equ "/a" echo 第一个参数是/a
/i 表示不区分大小写,equ 和 == 是一样的,其它运算符参见 if/?
if exist c:test.bat echo 存在c:test.bat文件
if not exist c:windows (
echo 不存在c:windows文件夹
)
if exist c:test.bat (
echo 存在c:test.bat
) else (
echo 不存在c:test.bat
)
30 setlocal 和 endlocal
设置”命令扩展名”和”延缓环境变量扩充”
SETLOCAL ENABLEEXTENSIONS #启用"命令扩展名"
SETLOCAL DISABLEEXTENSIONS #停用"命令扩展名"
SETLOCAL ENABLEDELAYEDEXPANSION #启用"延缓环境变量扩充"
SETLOCAL DISABLEDELAYEDEXPANSION #停用"延缓环境变量扩充"
ENDLOCAL #恢复到使用SETLOCAL语句以前的状态
“命令扩展名”默认为启用
“延缓环境变量扩充”默认为停用
批处理结束系统会自动恢复默认值
可以修改注册表以禁用"命令扩展名",详见 cmd /? 。所以用到"命令扩展名"的程
序,建议在开头和结尾加上 SETLOCAL ENABLEEXTENSIONS 和 ENDLOCAL 语句,以确
保程序能在其它系统上正确运行
"延缓环境变量扩充"主要用于 if 和 for 的符合语句,在 set 的说明里有其实用例程
31 set
设置变量
引用变量可在变量名前后加 % ,即 %变量名%
set #显示目前所有可用的变量,包括系统变量和自定义的变量
echo %SystemDrive% #显示系统盘盘符。系统变量可以直接引用
set p #显示所有以p开头的变量,要是一个也没有就设errorlevel=1
set p=aa1bb1aa2bb2 #设置变量p,并赋值为 = 后面的字符串,即aa1bb1aa2bb2
echo %p% #显示变量p代表的字符串,即aa1bb1aa2bb2
echo %p:~6% #显示变量p中第6个字符以后的所有字符,即aa2bb2
echo %p:~6,3% #显示第6个字符以后的3个字符,即aa2
echo %p:~0,3% #显示前3个字符,即aa1
echo %p:~-2% #显示最后面的2个字符,即b2
echo %p:~0,-2% #显示除了最后2个字符以外的其它字符,即aa1bb1aa2b
echo %p:aa=c% #用c替换变量p中所有的aa,即显示c1bb1c2bb2
echo %p:aa=% #将变量p中的所有aa字符串置换为空,即显示1bb12bb2
echo %p:*bb=c% #第一个bb及其之前的所有字符被替换为c,即显示c1aa2bb2
set p=%p:*bb=c% #设置变量p,赋值为 %p:*bb=c% ,即c1aa2bb2
set /a p=39 #设置p为数值型变量,值为39
set /a p=39/10 #支持运算符,有小数时用去尾法,39/10=3.9,去尾得3,p=3
set /a p=p/10 #用 /a 参数时,在 = 后面的变量可以不加%直接引用
set /a p=”1&0″ #”与”运算,要加引号。其它支持的运算符参见set/?
set p= #取消p变量
set /p p=请输入
屏幕上显示”请输入”,并会将输入的字符串赋值给变量p
注意这条可以用来取代 choice 命令
注意变量在 if 和 for 的复合语句里是一次性全部替换的,如
@echo off
set p=aaa
if %p%==aaa (
echo %p%
set p=bbb
echo %p%
)
结果将显示
aaa
aaa
因为在读取 if 语句时已经将所有 %p% 替换为aaa
这里的"替换",在 /? 帮助里就是指"扩充"、"环境变量扩充"
可以启用”延缓环境变量扩充”,用 ! 来引用变量,即 !变量名!
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set p=aaa
if %p%==aaa (
echo %p%
set p=bbb
echo !p!
)
ENDLOCAL
结果将显示
aaa
bbb
还有几个动态变量,运行 set 看不到
%CD% #代表当前目录的字符串
%DATE% #当前日期
%TIME% #当前时间
%RANDOM% #随机整数,介于0~32767
%ERRORLEVEL% #当前 ERRORLEVEL 值
%CMDEXTVERSION% #当前命令处理器扩展名版本号
%CMDCMDLINE% #调用命令处理器的原始命令行
可以用echo命令查看每个变量值,如 echo %time%
注意 %time% 精确到毫秒,在批处理需要延时处理时可以用到
32 start
批处理中调用外部程序的命令,否则等外部程序完成后才继续执行剩下的指令
33 call
批处理中调用另外一个批处理的命令,否则剩下的批处理指令将不会被执行
有时有的应用程序用start调用出错的,也可以call调用
34 choice (外部命令)
选择命令
让用户输入一个字符,从而选择运行不同的命令,返回码errorlevel为1234……
win98里是choice.com
win2000pro里没有,可以从win98里拷过来
win2003里是choice.exe
choice /N /C y /T 5 /D y>nul
延时5秒
35 assoc 和 ftype
文件关联
assoc 设置'文件扩展名'关联,关联到'文件类型'
ftype 设置'文件类型'关联,关联到'执行程序和参数'
当你双击一个.txt文件时,windows并不是根据.txt直接判断用 notepad.exe 打开
而是先判断.txt属于 txtfile '文件类型'
再调用 txtfile 关联的命令行 txtfile=%SystemRoot%system32NOTEPAD.EXE %1
可以在"文件夹选项"→"文件类型"里修改这2种关联
assoc #显示所有'文件扩展名'关联
assoc .txt #显示.txt代表的'文件类型',结果显示 .txt=txtfile
assoc .doc #显示.doc代表的'文件类型',结果显示 .doc=Word.Document.8
assoc .exe #显示.exe代表的'文件类型',结果显示 .exe=exefile
ftype #显示所有'文件类型'关联
ftype exefile #显示exefile类型关联的命令行,结果显示 exefile="%1" %*
assoc .txt=Word.Document.8
设置.txt为word类型的文档,可以看到.txt文件的图标都变了
assoc .txt=txtfile
恢复.txt的正确关联
ftype exefile="%1" %*
恢复 exefile 的正确关联
如果该关联已经被破坏,可以运行 command.com ,再输入这条命令
36 pushd 和 popd
切换当前目录
@echo off
c: & cd & md mp3 #在 C: 建立 mp3 文件夹
md d:mp4 #在 D: 建立 mp4 文件夹
cd /d d:mp4 #更改当前目录为 d:mp4
pushd c:mp3 #保存当前目录,并切换当前目录为 c:mp3
popd #恢复当前目录为刚才保存的 d:mp4
37 for
循环命令
这个比较复杂,请对照 for/? 来看
for %%i in (c: d: e: f:) do echo %%i
依次调用小括号里的每个字符串,执行 do 后面的命令
注意%%i,在批处理中 for 语句调用参数用2个%
默认的字符串分隔符是"空格键","Tab键","回车键"
for %%i in (*.txt) do find "abc" %%i
对当前目录里所有的txt文件执行 find 命令
for /r . %%i in (*.txt) do find "abc" %%i
在当前目录和子目录里所有的.txt文件中搜索包含 abc 字符串的行
for /r . %%i in (.) do echo %%~pni
显示当前目录名和所有子目录名,包括路径,不包括盘符
for /r d:mp3 %%i in (*.mp3) do echo %%i>>d:mp3.txt
把 d:mp3 及其子目录里的mp3文件的文件名都存到 d:mp3.txt 里去
for /l %%i in (2,1,8) do echo %%i
生成2345678的一串数字,2是数字序列的开头,8是结尾,1表示每次加1
for /f %%i in ('set') do echo %%i
对 set 命令的输出结果循环调用,每行一个
for /f "eol=P" %%i in ('set') do echo %%i
取 set 命令的输出结果,忽略以 P 开头的那几行
for /f %%i in (d:mp3.txt) do echo %%i
显示 d:mp3.txt 里的每个文件名,每行一个,不支持带空格的名称
for /f "delims=" %%i in (d:mp3.txt) do echo %%i
显示 d:mp3.txt 里的每个文件名,每行一个,支持带空格的名称
for /f "skip=5 tokens=4" %%a in ('dir') do echo %%a
对 dir 命令的结果,跳过前面5行,余下的每行取第4列
每列之间的分隔符为默认的"空格"
可以注意到 dir 命令输出的前5行是没有文件名的
for /f "tokens=1,2,3 delims=- " %%a in ('date /t') do (
echo %%a
echo %%b
echo %%c
)
对 date /t 的输出结果,每行取1、2、3列
第一列对应指定的 %%a ,后面的 %%b 和 %%c 是派生出来的,对应其它列
分隔符指定为 - 和"空格",注意 delims=- 后面有个"空格"
其中 tokens=1,2,3 若用 tokens=1-3 替换,效果是一样的
for /f "tokens=2* delims=- " %%a in ('date /t') do echo %%b
取第2列给 %%a ,其后的列都给 %%b
38 subst (外部命令)
映射磁盘。
subst z: serverd #这样输入z:就可以访问serverd了
subst z: /d #取消该映射
subst #显示目前所有的映时
39 xcopy (外部命令)
文件拷贝
xcopy d:mp3 e:mp3 /s/e/i/y
复制 d:mp3 文件夹、所有子文件夹和文件到 e: ,覆盖已有文件
加 /i 表示如果 e: 没有 mp3 文件夹就自动新建一个,否则会有询问
获取文件所在路径¶在开发时,经常需要使用批处理运行一些程序,java程序犹其是这样,往往需要运行时根路径。Hardcode一个路径总是令自己觉得不自在,例如一个java程序从一台机copy到另外一台机,盘符往往发生变化,先修改一下bat里的路径再运行显然很麻烦。 在批处理开头加入
Note
比如有个批处理文件 For循环命令¶基本格式: FOR 参数 %%变量名 IN (相关文件或命令) DO 执行的命令
可以在CMD输入 FOR %%variable IN (set) DO command [command-parameters]
无参数¶格式: FOR %variable IN (set) DO command [command-parameters]
示例: for %%i in (t*.*) do echo %%i --显示当前目录下与t*.*相匹配的文件(只显示文件名,不显示路径)
for %%i in (d:/mydocuments/*.doc) do @echo %%i --显示d:/mydocuments/目录下与*.doc相匹配的文件
D参数¶格式: FOR /D %variable IN (set) DO command [command-parameters] 这个参数主要用于目录搜索,不会搜索文件,/D 参数只能显示当前目录下的目录名字。(特别说明:只会搜索指定目录下的目录,不会搜索再下一级的目录。) 示例: for /d %%i in (c:/*) do echo %%i --显示c盘根目录下的所有目录
for /d %%i in (???) do echo %%i --显示当前目录下名字只有1-3个字母的目录
L参数¶格式: FOR /L %variable IN (start,step,end) DO command [command-parameters] 该集表示以增量形式从开始到结束的一个数字序列。可以使用负的 Step 示例: for /l %%i in (1,1,5) do @echo %%i --输出1 2 3 4 5
for /l %%i in (1,2,10) do @echo %%i --输出1,3,5,7,9
for /l %%i in (100,-20,1) do @echo %%i --输出100,80,60,40,20
for /l %%i in (1,1,5) do start cmd --打开5个CMD窗口
for /l %%i in (1,1,5) do md %%i --建立从1~5共5个文件夹
for /l %%i in (1,1,5) do rd /q %%i --删除从1~5共5个文件夹
R参数¶格式: FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters] 此命令会搜索指定路径及所有子目录中与set相符合的所有文件,注意是指定路径及所有子目录。
示例: for /r c:/ %%i in (boot.ini) do echo %%i --枚举了c盘所有目录
for /r d:/backup %%i in (1) do echo %%i --枚举d/backup目录
for /r c:/ %%i in (boot.ini) do if exist %%i echo %%i --很好的搜索命令,列举boot.ini存在的目录
for /r c:/ %%i in (*.exe) do echo %%i --把C盘根目录,和每个目录的子目录下面全部的EXE文件都列出来了!!!!
F参数¶这个参数是最难的,参数又多,先简单的解释一下:for命令带这个参数可以分析文件内容,字符串内容或某一命令输出的结果,并通过设置option得我们想要的结果。 以下是某高手的解释,感觉有点太专业了,自认为不太容易理解,也列一下:
格式:
示例1: FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k --
分析 myfile.txt 中的每一行,
eol=; --忽略以分号打头的那些行;
tokens=2,3* --将每行中的第二个和第三个符号传递给 for 程序体;
delims= , --用逗号和/或空格定界符号。
%i --这个 for 程序体的语句引用 %i 来取得取得的首个字符串(本例中为第二个符号),引用 %j 来取得第二个字符串(本例中为第三个符号)引用 %k来取得第三个符号后的所有剩余符号。
示例2: 1. 分析文件的例子: for /f "eol=; tokens=1,2* delims=,- " %%i in (d:/test.txt) do echo %%i %%j %%k
2. 分析字符串的例子: for /f "tokens=1,2,3* delims=-, " %%i in ("aa bb,cc-dd ee") do echo %%i %%j %%k %%l
3. 分析命令输出的例子: for /f "tokens=1* delims==" %%i IN ('set') DO @echo [%%i----%%j]
FOR命令中的变量: ~I - 删除任何引号("),扩充 %I
%~fI - 将 %I 扩充到一个完全合格的路径名
%~dI - 仅将 %I 扩充到一个驱动器号
%~pI - 仅将 %I 扩充到一个路径
%~nI - 仅将 %I 扩充到一个文件名
%~xI - 仅将 %I 扩充到一个文件扩展名
%~sI - 扩充的路径只含有短名
%~aI - 将 %I 扩充到文件的文件属性
%~tI - 将 %I 扩充到文件的日期/时间
%~zI - 将 %I 扩充到文件的大小
%~$PATH:I - 查找列在路径环境变量的目录(TTT提示:是环境变量path的目录),并将 %I 扩充到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩充到空字符串
%~dpI - 仅将 %I 扩充到一个驱动器号和路径
%~nxI - 仅将 %I 扩充到一个文件名和扩展名
%~fsI - 仅将 %I 扩充到一个带有短名的完整路径名
%~dp$PATH:i - 查找列在路径环境变量的目录,并将 %I 扩充到找到的第一个驱动器号和路径。
%~ftzaI - 将 %I 扩充到类似输出线路的 DIR
Note 在以上例子中,%I 和 PATH 可用其他有效数值代替。%~ 语法用一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名比较易读,而且避免与不分大小写的组合键混淆。 set命令¶[设置变量]
格式:set 变量名=变量值
详细:被设定的变量以 %变量名% 引用
[取消变量]
格式:set 变量名=
详细:取消后的变量若被引用 %变量名% 将为空
[展示变量]
格式:set 变量名
详细:展示以变量名开头的所有变量的值
[列出所有可用的变量]
格式:set
[计算器]
格式:set /a 表达式
示例:set /a 1+2*3 输出 7
Attention set不能用在复合语句里面比如 预定义的变量¶下面是些已经被底层定义好可以直接使用的变量:不会出现在 SET 显示的变量列表中: - %CD% - 扩展到当前目录字符串。
- %DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。
- %TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。
- %RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。
- %ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。
- %CMDEXTVERSION% - 扩展到当前命令处理器扩展名版本号。
- %CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。
- %0 bat的完整路径名如"C:\Windows\system32\xxx.bat"
- %1 bat参数1依次类推%2参数2...
- %path% - 当前的环境变量。以分号隔开的路径列表,路径可包含空格,可以以'\'结尾, 可以以双引号包围之。
扩展变量¶与%i相关的变量¶包括bat参数或者for循环的%i 假设文件为 %0 C:\Documents and Settings\jinsun\桌面\ParseSinglePkgs.bat
%~dp0 C:\Documents and Settings\jinsun\桌面\
%cd% C:\Documents and Settings\jinsun\桌面
%~nx0 ParseSinglePkgs.bat
%~n0 ParseSinglePkgs
%~x0 .bat
与%VAR%相关的变量¶%VAR:str1=str2% 会将VAR中的str1替换为str2(str2如果为空则达到删除的效果,str1前可以加*,变量%ABC:*B=%是C)
%VAR:~0,-2% 会提取VAR 变量的所有字符,除了最后两个
%VAR:~-2% 会提取VAR 变量的最后两个
系统变量¶他们的值由系统将其根据事先定义的条件自动赋值,我们只需要调用而已: %ALLUSERSPROFILE% (allusersprofile)本地 返回“所有用户”配置文件的位置。 C:Documents and SettingsAll Users
%APPDATA% (appdata)本地返回默认情况下应用程序存储数据的位置。 C:Documents and SettingsAdministratorApplication Data
%CD% (cd)本地返回当前目录字符串。 C:Documents and SettingsAdministrator桌面
%CMDCMDLINE% (cmdcmdline)本地返回用来启动当前的 Cmd.exe 的准确命令行。 cmd /c ""C:Documents and SettingsAdministrator桌面a.bat" "
%CMDEXTVERSION%(cmdextversion)系统返回当前的“命令处理程序扩展”的版本号。2
%COMPUTERNAME% (computername)系统返回计算机的名称。 xxxx
%COMSPEC% (comspec) 系统返回命令行解释器可执行程序的准确路径。 C:WINDOWSsystem32cmd.exe
%DATE% 系统返回当前日期。使用与 date /t 命令相同的格式。由 Cmd.exe 生成。有关 date 命令的详细信息,请参阅 Date。
%ERRORLEVEL% (errorlevel) 系统返回上一条命令的错误代码。通常用非零值表示错误。
%HOMEDRIVE% (homedrive)系统返回连接到用户主目录的本地工作站驱动器号。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 C:
%HOMEPATH% (homepath) 系统返回用户主目录的完整路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 Documents and SettingsAdministrator
%HOMESHARE% (homeshare) 系统返回用户的共享主目录的网络路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。
%LOGONSERVER% (logonserver) 本地返回验证当前登录会话的域控制器的名称 \ xxxx
%NUMBER_OF_PROCESSORS% (numeer_of_processors) 系统指定安装在计算机上的处理器的数目。
%OS% (os)系统返回操作系统名称。Windows 2000 显示其操作系统为 Windows_NT。 Windows_NT
%PATH% (path)系统指定可执行文件的搜索路径。 C:WINDOWSsystem32;C:WINDOWS;C:WINDOWSSystem32Wbem;C:Program FilesVc++ToolsWinNT;C:Program FilesVc++MSDev98Bin;C:Program FilesVc++Tools;C:Program FilesVC98in
%PATHEXT% (pathext)系统返回操作系统认为可执行的文件扩展名的列表。 .COM .EXE .BAT .CMD .VBS .VBE .JS .JSE .WSF .WSH
%PROCESSOR_ARCHITECTURE% (processor_architecture) 系统返回处理器的芯片体系结构。值:x86 或 IA64 基于Itanium x86
%PROCESSOR_IDENTFIER% (processor_identfier)系统返回处理器说明。
%PROCESSOR_LEVEL% (processor_level)系统返回计算机上安装的处理器的型号。 15
%PROCESSOR_REVISION% (processor_revision)系统返回处理器的版本号。 4f02
%PROMPT% (prompt)本地 返回当前解释程序的命令提示符设置。由 Cmd.exe 生成。$P$G
%RANDOM% (random)系统返回 0 到 32767 之间的任意十进制数字。由 Cmd.exe 生成。 30580
%SYSTEMDRIVE% (systemdrive)系统返回包含 Windows server operating system 根目录(即系统根目录)的驱动器。 C:
%SYSTEMROOT% (systemroot)系统返回 Windows server operating system 根目录的位置。C:WINDOWS
%TEMP%(temp) C:DOCUME~1ADMINI~1LOCALS~1Temp和 %TMP% (tmp)C:DOCUME~1ADMINI~1LOCALS~1Temp系统和用户返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP,而其他应用程序则需要 TMP。
%TIME% 系统 返回当前时间。使用与 time /t 命令相同的格式。由 Cmd.exe 生成。有关 time 命令的详细信息,请参阅 Time。
%USERDOMAIN% (userdomain)本地返回包含用户帐户的域的名称。 xxxx
%USERNAME% (username)本地返回当前登录的用户的名称。 Administrator
%USERPROFILE% (userprofile)本地返回当前用户的配置文件的位置。 C:Documents and SettingsAdministrator
%WINDIR%(windir) 系统 返回操作系统目录的位置。 C:WINDOWS
echo输出多行内容到文件¶执行echo时,如果用 name=bash
echo “my name is $name” > file.txt
cat file.txt
“my name is bash”
因此这种情况下,输出字符串后面带不带’n’都不会换行 如果用 注释语句¶写bat批处理也一样,都要用到注释的功能,这是为了程式的可读性 在批处理中,段注释有一种比较常用的方法: goto start
= 可以是多行文本,可以是命令
= 可以包含重定向符号和其他特殊字符
= 只要不包含 :start 这一行,就都是注释
:start
另外,还有其他各种注释形式,比如:
Linux工具快速教程¶原文地址: https://linuxtools-rst.readthedocs.io/zh_CN/latest/index.html 前言 Linux下有很多命令行工具供我们使用,每个工具总是提供了大量参数供我们选择; 实际工作中,我们用到的工具,最常用的总是那么几个参数组合; 为此,我写了这本书相对实用的书; 这本书专注于Linux工具的最常用用法,以便读者能以最快时间掌握,并在工作中应用; 说明 全书分为三个部分:
同时,这个教程也可当作Linux命令手册使用,使用左边栏的目录和搜索栏可以很方便的查阅; 建议
写作工具 本书使用的reStructuredText标记语言,相对Markdown来说,在写书方面更有优势:
版权声明 Note 本书为开源图书,版权归作者所有;欢迎下载及编辑(个人用途),但未经作者同意必须保留此段声明,且不可用于商业用途,否则保留追究法律责任的权利。
目录 Linux基础¶这一部分主要介绍Linux常用命令工具,比如文件管理、文本处理;为了让读者用最少的时间掌握到常用的知识,对于每个工具的举例,尽量做到小而精; Note 本书并非一本讲解Linux各种命令的完整用法的书,并且假设读者已经熟悉Linux命令行下的基本操作。如果读者对Linux操作系统尚不了解,可以参考 《鸟哥的私房菜 基础学习篇》[1]一书。 学会使用命令帮助¶概述¶在linux终端,面对命令不知道怎么用,或不记得命令的拼写及参数时,我们需要求助于系统的帮助文档; linux系统内置的帮助文档很详细,通常能解决我们的问题,我们需要掌握如何正确的去使用它们;
下面介绍这些命令; 命令使用¶简要说明命令的作用(显示命令所处的man分类页面): $whatis command
正则匹配: $whatis -w "loca*"
更加详细的说明文档: $info command
查询命令command的说明文档: $man command
eg:man date
使用page up和page down来上下翻页 在man的帮助手册中,将帮助文档分为了9个类别,对于有的关键字可能存在多个类别中, 我们就需要指定特定的类别来查看;(一般我们查询bash命令,归类在1类中); man页面所属的分类标识(常用的是分类1和分类3) (1)、用户可以操作的命令或者是可执行文件
(2)、系统核心可调用的函数与工具等
(3)、一些常用的函数与数据库
(4)、设备文件的说明
(5)、设置文件或者某些文件的格式
(6)、游戏
(7)、惯例与协议等。例如Linux标准文件系统、网络协议、ASCⅡ,码等说明内容
(8)、系统管理员可用的管理条令
(9)、与内核有关的文件
前面说到使用whatis会显示命令所在的具体的文档类别,我们学习如何使用它 eg:
$whatis printf
printf (1) - format and print data
printf (1p) - write formatted output
printf (3) - formatted output conversion
printf (3p) - print formatted output
printf [builtins] (1) - bash built-in commands, see bash(1)
我们看到printf在分类1和分类3中都有;分类1中的页面是命令操作及可执行文件的帮助;而3是常用函数库说明;如果我们想看的是C语言中printf的用法,可以指定查看分类3的帮助: $man 3 printf
$man -k keyword
查询关键字 根据命令中部分关键字来查询命令,适用于只记住部分命令的场合; eg:查找GNOME的config配置工具命令: $man -k GNOME config| grep 1
对于某个单词搜索,可直接使用/word来使用: /-a; 多关注下SEE ALSO 可看到更多精彩内容 查看程序的binary文件所在路径: $which command
eg:查找make程序安装路径: $which make
/opt/app/openav/soft/bin/make install
查看程序的搜索路径: $whereis command
当系统中安装了同一软件的多个版本时,不确定使用的是哪个版本时,这个命令就能派上用场; whatis info man which whereis 文件及目录管理¶目录 文件管理不外乎文件或目录的创建、删除、查询、移动,有mkdir/rm/mv 文件查询是重点,用find来进行查询;find的参数丰富,也非常强大; 查看文件内容是个大的话题,文本的处理有太多的工具供我们使用,在本章中只是点到即止,后面会有专门的一章来介绍文本的处理工具; 有时候,需要给文件创建一个别名,我们需要用到ln,使用这个别名和使用原文件是相同的效果; 创建和删除¶
查看当前目录下文件个数: $find ./ | wc -l
复制目录: $cp -r source_dir dest_dir
列出目录项¶
以上这个命令用到的频率如此之高,以至于我们需要为它建立一个快捷命令方式: 在.bashrc 中设置命令别名: alias lsl='ls -lrt'
alias lm='ls -al|more'
这样,使用lsl,就可以显示目录中的文件按照修改时间排序;以列表方式显示;
注:.bashrc 在/home/你的用户名/ 文件夹下,以隐藏文件的方式存储;可使用 ls -a 查看; 查找目录及文件 find/locate¶搜寻文件或目录: $find ./ -name "core*" | xargs file
查找目标文件夹中是否有obj文件: $find ./ -name '*.o'
递归当前目录及子目录删除所有.o文件: $find ./ -name "*.o" -exec rm {} \;
find是实时查找,如果需要更快的查询,可试试locate;locate会为文件系统建立索引数据库,如果有文件更新,需要定期执行更新命令来更新索引库: $locate string
寻找包含有string的路径: $updatedb
与find不同,locate并不是实时查找。你需要更新数据库,以获得最新的文件索引信息。 查看文件内容¶查看文件:cat vi head tail more 显示时同时显示行号: $cat -n
按页显示列表内容: $ls -al | more
只看前10行: $head - 10 **
显示文件第一行: $head -1 filename
显示文件倒数第五行: $tail -5 filename
查看两个文件间的差别: $diff file1 file2
动态显示文本最新信息: $tail -f crawler.log
查找文件内容¶使用egrep查询文件内容: egrep '03.1\/CO\/AE' TSF_STAT_111130.log.012
egrep 'A_LMCA777:C' TSF_STAT_111130.log.035 > co.out2
文件与目录权限修改¶
给文件增加别名¶创建符号链接/硬链接: ln cc ccAgain :硬连接;删除一个,将仍能找到;
ln -s cc ccTo :符号链接(软链接);删除源,另一个无法使用;(后面一个ccTo 为新建的文件)
管道和重定向¶
ls /proc && echo suss! || echo failed.
能够提示命名是否执行成功or失败; 与上述相同效果的是: if ls /proc; then echo suss; else echo fail; fi
重定向: ls proc/*.c > list 2> &l 将标准输出和标准错误重定向到同一文件;
等价的是: ls proc/*.c &> list
清空文件: :> a.txt
重定向: echo aa >> a.txt
设置环境变量¶启动帐号后自动执行的是 文件为 .profile,然后通过这个文件可设置自己的环境变量; 安装的软件路径一般需要加入到path中: PATH=$APPDIR:/opt/app/soft/bin:$PATH:/usr/local/bin:$TUXDIR/bin:$ORACLE_HOME/bin;export PATH
Bash快捷输入或删除¶快捷键: Ctl-U 删除光标到行首的所有字符,在某些设置下,删除全行
Ctl-W 删除当前光标到前边的最近一个空格之间的字符
Ctl-H backspace,删除光标前边的字符
Ctl-R 匹配最相近的一个文件,然后输出
文本处理¶目录 本节将介绍Linux下使用Shell处理文本时最常用的工具: find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk; 提供的例子和参数都是常用的; 我对shell脚本使用的原则是命令单行书写,尽量不要超过2行; 如果有更为复杂的任务需求,还是考虑python吧; find 文件查找¶查找txt和pdf文件: find . \( -name "*.txt" -o -name "*.pdf" \) -print
正则方式查找.txt和pdf: find . -regex ".*\(\.txt|\.pdf\)$"
-iregex: 忽略大小写的正则 否定参数 ,查找所有非txt文本: find . ! -name "*.txt" -print
指定搜索深度,打印出当前目录的文件(深度为1): find . -maxdepth 1 -type f
-type f 文件 / l 符号链接 / d 目录 find支持的文件检索类型可以区分普通文件和符号链接、目录等,但是二进制文件和文本文件无法直接通过find的类型区分出来; file命令可以检查文件具体类型(二进制或文本): $file redis-cli # 二进制文件
redis-cli: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
$file redis.pid # 文本文件
redis.pid: ASCII text
所以,可以用以下命令组合来实现查找本地目录下的所有二进制文件: ls -lrt | awk '{print $9}'|xargs file|grep ELF| awk '{print $1}'|tr -d ':'
最近第7天被访问过的所有文件: find . -atime 7 -type f -print
最近7天内被访问过的所有文件: find . -atime -7 -type f -print
查询7天前被访问过的所有文件: find . -atime +7 type f -print
w字 k M G 寻找大于2k的文件: find . -type f -size +2k
按权限查找: find . -type f -perm 644 -print //找具有可执行权限的所有文件
按用户查找: find . -type f -user weber -print// 找用户weber所拥有的文件
删除当前目录下所有的swp文件: find . -type f -name "*.swp" -delete
另一种语法: find . type f -name "*.swp" | xargs rm
将当前目录下的所有权变更为weber: find . -type f -user root -exec chown weber {} \;
注:{}是一个特殊的字符串,对于每一个匹配的文件,{}会被替换成相应的文件名; 将找到的文件全都copy到另一个目录: find . -type f -mtime +10 -name "*.txt" -exec cp {} OLD \;
如果需要后续执行多个命令,可以将多个命令写成一个脚本。然后 -exec 调用时执行脚本即可: -exec ./commands.sh {} \;
grep 文本搜索¶grep match_patten file // 默认访问匹配行
常用参数
在多级目录中对文本递归搜索(程序员搜代码的最爱): grep "class" . -R -n
匹配多个模式: grep -e "class" -e "vitural" file
grep输出以0作为结尾符的文件名(-z): grep "test" file* -lZ| xargs -0 rm
综合应用:将日志中的所有带where条件的sql查找查找出来: cat LOG.* | tr a-z A-Z | grep "FROM " | grep "WHERE" > b
查找中文示例:工程目录中utf-8格式和gb2312格式两种文件,要查找字的是中文;
汉字编码查询:http://bm.kdd.cc/ xargs 命令行参数转换¶xargs 能够将输入数据转化为特定命令的命令行参数;这样,可以配合很多命令来组合使用。比如grep,比如find; - 将多行输出转化为单行输出 cat file.txt| xargs
n 是多行文本间的定界符
cat single.txt | xargs -n 3
-n:指定每行显示的字段数 xargs参数说明
示例: cat file.txt | xargs -I {} ./command.sh -p {} -1
#统计程序行数
find source_dir/ -type f -name "*.cpp" -print0 |xargs -0 wc -l
#redis通过string存储数据,通过set存储索引,需要通过索引来查询出所有的值:
./redis-cli smembers $1 | awk '{print $1}'|xargs -I {} ./redis-cli get {}
sort 排序¶字段说明
示例: sort -nrk 1 data.txt
sort -bd data // 忽略像空格之类的前导空白字符
uniq 消除重复行¶
sort unsort.txt | uniq
sort unsort.txt | uniq -c
sort unsort.txt | uniq -d
可指定每行中需要比较的重复内容:-s 开始位置 -w 比较字符数 用tr进行转换¶
echo 12345 | tr '0-9' '9876543210' //加解密转换,替换对应字符
cat text| tr '\t' ' ' //制表符转空格
cat file | tr -d '0-9' // 删除所有数字
-c 求补集 cat file | tr -c '0-9' //获取文件中所有数字
cat file | tr -d -c '0-9 \n' //删除非数字数据
tr -s 压缩文本中出现的重复字符;最常用于压缩多余的空格: cat file | tr -s ' '
使用方法:tr [:class:] [:class:] tr '[:lower:]' '[:upper:]'
cut 按列切分文本¶
cut -f2,4 filename
cut -f3 --complement filename
cat -f2 -d";" filename
示例: cut -c1-5 file //打印第一到5个字符
cut -c-2 file //打印前2个字符
截取文本的第5到第7列 $echo string | cut -c5-7
paste 按列拼接文本¶将两个文本按列拼接到一起; cat file1
1
2
cat file2
colin
book
paste file1 file2
1 colin
2 book
默认的定界符是制表符,可以用-d指明定界符: paste file1 file2 -d ","
1,colin
2,book
wc 统计行和字符的工具¶$wc -l file // 统计行数
$wc -w file // 统计单词数
$wc -c file // 统计字符数
sed 文本替换利器¶
sed 's/text/replace_text/' file //替换每一行的第一处匹配的text
sed 's/text/replace_text/g' file
默认替换后,输出替换后的内容,如果需要直接替换原文件,使用-i: sed -i 's/text/repalce_text/g' file
sed '/^$/d' file
已匹配的字符串通过标记&来引用. echo this is en example | sed 's/\w+/[&]/g'
$>[this] [is] [en] [example]
第一个匹配的括号内容使用标记 1 来引用 sed 's/hello\([0-9]\)/\1/'
sed通常用单引号来引用;也可使用双引号,使用双引号后,双引号会对表达式求值: sed 's/$var/HLLOE/'
当使用双引号时,我们可以在sed样式和替换字符串中指定变量; eg:
p=patten
r=replaced
echo "line con a patten" | sed "s/$p/$r/g"
$>line con a replaced
字符串插入字符:将文本中每行内容(ABCDEF) 转换为 ABC/DEF: sed 's/^.\{3\}/&\//g' file
awk 数据流处理工具¶
awk ' BEGIN{ statements } statements2 END{ statements } '
1.执行begin中语句块; 2.从文件或stdin中读入一行,然后执行statements2,重复这个过程,直到文件全部被读取完毕; 3.执行end语句块;
echo -e "line1\nline2" | awk 'BEGIN{print "start"} {print } END{ print "End" }'
echo | awk ' {var1 = "v1" ; var2 = "V2"; var3="v3"; \
print var1, var2 , var3; }'
$>v1 V2 v3
echo | awk ' {var1 = "v1" ; var2 = "V2"; var3="v3"; \
print var1"-"var2"-"var3; }'
$>v1-V2-v3
NR:表示记录数量,在执行过程中对应当前行号; NF:表示字段数量,在执行过程总对应当前行的字段数; $0:这个变量包含执行过程中当前行的文本内容; $1:第一个字段的文本内容; $2:第二个字段的文本内容; echo -e "line1 f2 f3\n line2 \n line 3" | awk '{print NR":"$0"-"$1"-"$2}'
var=1000
echo | awk '{print vara}' vara=$var # 输入来自stdin
awk '{print vara}' vara=$var file # 输入来自文件
awk 'NR < 5' #行号小于5
awk 'NR==1,NR==4 {print}' file #行号等于1和4的打印出来
awk '/linux/' #包含linux文本的行(可以用正则表达式来指定,超级强大)
awk '!/linux/' #不包含linux文本的行
使用getline,将外部shell命令的输出读入到变量cmdout中: echo | awk '{"grep root /etc/passwd" | getline cmdout; print cmdout }'
for(i=0;i<10;i++){print $i;}
for(i in array){print array[i];}
eg:以下字符串,打印出其中的时间串: 2015_04_02 20:20:08: mysqli connect failed, please check connect info
$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F ":" '{ for(i=1;i<=;i++) printf("%s:",$i)}'
>2015_04_02 20:20:08: # 这种方式会将最后一个冒号打印出来
$echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F':' '{print $1 ":" $2 ":" $3; }'
>2015_04_02 20:20:08 # 这种方式满足需求
而如果需要将后面的部分也打印出来(时间部分和后文分开打印): $echo '2015_04_02 20:20:08: mysqli connect failed, please check connect info'|awk -F':' '{print $1 ":" $2 ":" $3; print $4;}'
>2015_04_02 20:20:08
>mysqli connect failed, please check connect info
以逆序的形式打印行:(tac命令的实现): seq 9| \
awk '{lifo[NR] = $0; lno=NR} \
END{ for(;lno>-1;lno--){print lifo[lno];}
} '
ps -fe| grep msv8 | grep -v MFORWARD | awk '{print $2}' | xargs kill -9;
打印处于start_pattern 和end_pattern之间的文本: awk '/start_pattern/, /end_pattern/' filename
示例a_error_sum
index(string,search_string):返回search_string在string中出现的位置 sub(regex,replacement_str,string):将正则匹配到的第一处内容替换为replacement_str; match(regex,string):检查正则表达式是否能够匹配字符串; length(string):返回字符串长度 echo | awk '{"grep root /etc/passwd" | getline cmdout; print length(cmdout) }'
printf 类似c语言中的printf,对输出进行格式化: seq 10 | awk '{printf "->%4s\n", $1}'
迭代文件中的行、单词和字符¶
for word in $line;
do
echo $word;
done
${string:start_pos:num_of_chars}:从字符串中提取一个字符;(bash文本切片) ${#word}:返回变量word的长度 for((i=0;i<${#word};i++))
do
echo ${word:i:1);
done
以ASCII字符显示文件: $od -c filename
磁盘管理¶日程磁盘管理中,我们最常用的有查看当前磁盘使用情况,查看当前目录所占大小,以及打包压缩与解压缩; 查看磁盘空间¶查看磁盘空间利用大小: df -h
-h: human缩写,以易读的方式显示结果(即带单位:比如M/G,如果不加这个参数,显示的数字以B为单位) $df -h
/opt/app/todeav/config#df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
2.0G 711M 1.2G 38% /
/dev/mapper/vg1-lv2 20G 3.8G 15G 21% /opt/applog
/dev/mapper/vg1-lv1 20G 13G 5.6G 70% /opt/app
查看当前目录所占空间大小: du -sh
$du -sh
653M
查看当前目录下所有子文件夹排序后的大小: for i in `ls`; do du -sh $i; done | sort
或者:
du -sh `ls` | sort
打包/ 压缩¶在linux中打包和压缩和分两步来实现的; 打包 打包是将多个文件归并到一个文件: tar -cvf etc.tar /etc <==仅打包,不压缩!
注:有的系统中指定参数时不需要在前面加上-,直接使用tar xvf 示例:用tar实现文件夹同步,排除部分文件不同步: tar --exclude '*.svn' -cvf - /path/to/source | ( cd /path/to/target; tar -xf -)
压缩 $gzip demo.txt
生成 demo.txt.gz 解包/解压缩¶解包 tar -xvf demo.tar
-x 解包选项 解压后缀为 .tar.gz的文件 1. 先解压缩,生成**.tar: $gunzip demo.tar.gz
bz2解压: tar jxvf demo.tar.bz2
如果tar 不支持j,则同样需要分两步来解包解压缩,使用bzip2来解压,再使用tar解包: bzip2 -d demo.tar.bz2
tar -xvf demo.tar
-d decompose,解压缩 tar解压参数说明:
进程管理工具¶这一节我们介绍进程管理工具; 使用进程管理工具,我们可以查询程序当前的运行状态,或终止一个进程; 任何进程都与文件关联;我们会用到lsof工具(list opened files),作用是列举系统中已经被打开的文件。在linux环境中,任何事物都是文件,设备是文件,目录是文件,甚至sockets也是文件。用好lsof命令,对日常的linux管理非常有帮助。 查询进程¶查询正在运行的进程信息 $ps -ef
eg:查询归属于用户colin115的进程 $ps -ef | grep colin115
$ps -lu colin115
查询进程ID(适合只记得部分进程字段) $pgrep 查找进程
eg:查询进程名中含有re的进程
[/home/weber#]pgrep -l re
2 kthreadd
28 ecryptfs-kthrea
29515 redis-server
以完整的格式显示所有的进程 $ps -ajx
显示进程信息,并实时更新 $top
查看端口占用的进程状态: lsof -i:3306
查看用户username的进程所打开的文件 $lsof -u username
查询init进程当前打开的文件 $lsof -c init
查询指定的进程ID(23295)打开的文件: $lsof -p 23295
查询指定目录下被进程开启的文件(使用+D 递归目录): $lsof +d mydir1/
进程监控¶查看系统中使用CPU、使用内存最多的进程; $top
(->)P
输入top命令后,进入到交互界面;接着输入字符命令后显示相应的进程状态: 对于进程,平时我们最常想知道的就是哪些进程占用CPU最多,占用内存最多。以下两个命令就可以满足要求: P:根据CPU使用百分比大小进行排序。
M:根据驻留内存大小进行排序。
i:使top不显示任何闲置或者僵死进程。
这里介绍最使用的几个选项,对于更详细的使用,详见 ref:top ; 分析线程栈¶使用命令pmap,来输出进程内存的状况,可以用来分析线程堆栈; $pmap PID
eg:
[/home/weber#]ps -fe| grep redis
weber 13508 13070 0 08:14 pts/0 00:00:00 grep --color=auto redis
weber 29515 1 0 2013 ? 02:55:59 ./redis-server redis.conf
[/home/weber#]pmap 29515
29515: ./redis-server redis.conf
08048000 768K r-x-- /home/weber/soft/redis-2.6.16/src/redis-server
08108000 4K r---- /home/weber/soft/redis-2.6.16/src/redis-server
08109000 12K rw--- /home/weber/soft/redis-2.6.16/src/redis-server
性能监控¶在使用操作系统的过程中,我们经常需要查看当前的性能如何,需要了解CPU、内存和硬盘的使用情况; 本节介绍的这几个工具能满足日常工作要求; 监控CPU¶查看CPU使用率 $sar -u
eg:
$sar -u 1 2
[/home/weber#]sar -u 1 2
Linux 2.6.35-22-generic-pae (MyVPS) 06/28/2014 _i686_ (1 CPU)
09:03:59 AM CPU %user %nice %system %iowait %steal %idle
09:04:00 AM all 0.00 0.00 0.50 0.00 0.00 99.50
09:04:01 AM all 0.00 0.00 0.00 0.00 0.00 100.00
后面的两个参数表示监控的频率,比如例子中的1和2,表示每秒采样一次,总共采样2次; 查看CPU平均负载 $sar -q 1 2
sar指定-q后,就能查看运行队列中的进程数、系统上的进程大小、平均负载等; 查询内存¶查看内存使用状况 sar指定-r之后,可查看内存使用状况; $sar -r 1 2
09:08:48 AM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact
09:08:49 AM 17888 359784 95.26 37796 73272 507004 65.42 137400 150764
09:08:50 AM 17888 359784 95.26 37796 73272 507004 65.42 137400 150764
Average: 17888 359784 95.26 37796 73272 507004 65.42 137400 150764
查看内存使用量 $free -m
查询页面交换¶查看页面交换发生状况 页面发生交换时,服务器的吞吐量会大幅下降;服务器状况不良时,如果怀疑因为内存不足而导致了页面交换的发生,可以使用sar -W这个命令来确认是否发生了大量的交换; $sar -W 1 3
查询硬盘使用¶查看磁盘空间利用情况 $df -h
查询当前目录下空间使用情况 du -sh -h是人性化显示 s是递归整个目录的大小
查看该目录下所有文件夹的排序后的大小 for i in `ls`; do du -sh $i; done | sort
或者
du -sh `ls`
综合应用¶当系统中sar不可用时,可以使用以下工具替代:linux下有 vmstat、Unix系统有prstat eg: 查看cpu、内存、使用情况: vmstat n m (n 为监控频率、m为监控次数) [/home/weber#]vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 86560 42300 9752 63556 0 1 1 1 0 0 0 0 99 0
1 0 86560 39936 9764 63544 0 0 0 52 66 95 5 0 95 0
0 0 86560 42168 9772 63556 0 0 0 20 127 231 13 2 84 0
使用watch 工具监控变化 当需要持续的监控应用的某个数据变化时,watch工具能满足要求; 执行watch命令后,会进入到一个界面,输出当前被监控的数据,一旦数据变化,便会高亮显示变化情况; eg:操作redis时,监控内存变化: $watch -d -n 1 './redis-cli info | grep memory'
(以下为watch工具中的界面内容,一旦内存变化,即实时高亮显示变化)
Every 1.0s: ./redis-cli info | grep memory Mon Apr 28 16:10:36 2014
used_memory:45157376
used_memory_human:43.07M
used_memory_rss:47628288
used_memory_peak:49686080
used_memory_peak_human:47.38M
网络工具¶查询网络服务和端口¶netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。 列出所有端口 (包括监听和未监听的): netstat -a
列出所有 tcp 端口: netstat -at
列出所有有监听的服务状态: netstat -l
使用netstat工具查询端口: $netstat -antp | grep 6379
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 25501/redis-server
$ps 25501
PID TTY STAT TIME COMMAND
25501 ? Ssl 28:21 ./redis-server ./redis.conf
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等; 在查询网络端口时,经常会用到这个工具。 查询7902端口现在运行什么程序: #分为两步
#第一步,查询使用该端口的进程的PID;
$lsof -i:7902
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
WSL 30294 tuapp 4u IPv4 447684086 TCP 10.6.50.37:tnos-dp (LISTEN)
#查到30294
#使用ps工具查询进程详情:
$ps -fe | grep 30294
tdev5 30294 26160 0 Sep10 ? 01:10:50 tdesl -k 43476
root 22781 22698 0 00:54 pts/20 00:00:00 grep 11554
Note 以上介绍lsof关于网络方面的应用,这个工具非常强大,需要好好掌握,详见 ref:lsof ; 网络路由¶查看路由状态: $route -n
发送ping包到地址IP: $ping IP
探测前往地址IP的路由路径: $traceroute IP
DNS查询,寻找域名domain对应的IP: $host domain
反向DNS查询: $host IP
ftp sftp lftp ssh¶SSH登陆: $ssh ID@host
ssh登陆远程服务器host,ID为用户名。 ftp/sftp文件传输: $sftp ID@host
登陆服务器host,ID为用户名。sftp登陆后,可以使用下面的命令进一步操作:
lftp同步文件夹(类似rsync工具): lftp -u user:pass host
lftp user@host:~> mirror -n
用户管理工具¶用户¶用户的组¶用户权限¶使用ls -l可查看文件的属性字段,文件属性字段总共有10个字母组成,第一个字母表示文件类型,如果这个字母是一个减号”-“,则说明该文件是一个普通文件。字母”d”表示该文件是一个目录,字母”d”,是dirtectory(目录)的缩写。 后面的9个字母为该文件的权限标识,3个为一组,分别表示文件所属用户、用户所在组、其它用户的读写和执行权限; 例如: [/home/weber#]ls -l /etc/group
-rwxrw-r-- colin king 725 2013-11-12 15:37 /home/colin/a
表示这个文件对文件拥有者colin这个用户可读写、可执行;对colin所在的组(king)可读可写;对其它用户只可读; 使用chmod命令更改文件的读写权限,更改读写权限有两种方法,一种是字母方式,一种是数字方式 字母方式: $chmod userMark(+|-)PermissionsMark
userMark取值:
PermissionsMark取值:
例如: $chmod a+x main 对所有用户给文件main增加可执行权限
$chmod g+w blogs 对组用户给文件blogs增加可写权限
数字方式: 数字方式直接设置所有权限,相比字母方式,更加简洁方便; 使用三位八进制数字的形式来表示权限,第一位指定属主的权限,第二位指定组权限,第三位指定其他用户的权限,每位通过4(读)、2(写)、1(执行)三种数值的和来确定权限。如6(4+2)代表有读写权,7(4+2+1)有读、写和执行的权限。 例如: $chmod 740 main 将main的用户权限设置为rwxr-----
环境变量¶bashrc与profile都用于保存用户的环境信息,bashrc用于交互式non-loginshell,而profile用于交互式login shell。 /etc/profile,/etc/bashrc 是系统全局环境变量设定
~/.profile,~/.bashrc用户目录下的私有环境变量设定
当登入系统获得一个shell进程时,其读取环境设置脚本分为三步:
~/.profile与~/.bashrc的区别:
例如,我们可以在这些环境变量中设置自己经常进入的文件路径,以及命令的快捷方式: .bashrc
alias m='more'
alias cp='cp -i'
alias mv='mv -i'
alias ll='ls -l'
alias lsl='ls -lrt'
alias lm='ls -al|more'
log=/opt/applog/common_dir
unit=/opt/app/unittest/common
.bash_profile
. /opt/app/tuxapp/openav/config/setenv.prod.sh.linux
export PS1='$PWD#'
通过上述设置,我们进入log目录就只需要输入cd $log即可; 系统管理及IPC资源管理¶系统管理¶IPC资源管理¶查看系统使用的IPC资源: $ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 229376 weber 600 1
------ Message Queues --------
key msqid owner perms used-bytes messages
查看系统使用的IPC共享内存资源: $ipcs -m
查看系统使用的IPC队列资源: $ipcs -q
查看系统使用的IPC信号量资源: $ipcs -s
应用示例:查看IPC资源被谁占用 有个IPCKEY:51036 ,需要查询其是否被占用;
Linux工具进阶¶程序篇 程序构建¶一般源代码提供的程序安装需要通过配置、编译、安装三个步骤;
配置¶查询可用的配置选项: ./configure --help
配置路径: ./configure --prefix=/usr/local/snmp
–prefix是配置使用的最常用选项,设置程序安装的路径; 编译¶编译使用make编译: make -f myMakefile
通过-f选项显示指定需要编译的makefile;如果待使用makefile文件在当前路径,且文件名为以下几个,则不用显示指定: makefile Makefile
Note 系统学习makefile的书写规则,请参考 跟我一起学makefile [1] CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件。使用CMake,能够使程序员从复杂的编译连接过程中解脱出来。它使用一个名为 CMakeLists.txt 的文件来描述构建过程,可以生成标准的构建文件,如 Unix/Linux 的 Makefile 或Windows Visual C++ 的 projects/workspaces 。 makefile编译过程中所依赖的非标准库和头文件路径需要显示指明: CPPFLAGS -I标记非标准头文件存放路径
LDFLAGS -L标记非标准库存放路径
如果CPPFLAGS和LDFLAGS已在用户环境变量中设置并且导出(使用export关键字),就不用再显示指定; make -f myMakefile LDFLAGS='-L/var/xxx/lib -L/opt/mysql/lib'
CPPFLAGS='-I/usr/local/libcom/include -I/usr/local/libpng/include'
Caution 链接多库时,多个库之间如果有依赖,需要注意书写的顺序,右边是左边的前提; g++ -o unixApp unixApp.o a.o b.o
选项说明:
应用:查询宏展开的中间文件: 在g++的编译选项中,添加 -E选项,然后去掉-o选项 ,重定向到一个文件中即可: g++ -g -E unixApp.cpp -I/opt/app/source > midfile
查询应用程序需要链接的库: $ldd myprogrammer
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00000039a7e00000)
libm.so.6 => /lib64/libm.so.6 (0x0000003996400000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000039a5600000)
libc.so.6 => /lib64/libc.so.6 (0x0000003995800000)
/lib64/ld-linux-x86-64.so.2 (0x0000003995400000)
Note 关于ldd的使用细节,参见 ldd 查看程序依赖库 安装¶安装做的工作就简单多了,就是将生成的可执行文件拷贝到配置时设置的初始路径下: $make install
其实 install 就是makefile中的一个规则,打开makefile文件后可以查看程序安装的所做的工作; 总结¶configure make install g++
程序调试¶目录 进程调试¶GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c++程序员,gdb是必不可少的工具; GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调试工作。 以下从一个完整的调试过程简单说明最基本的几个命令; $gdb programmer # 启动gdb
>break main # 设置断点
>run # 运行调试程序
>next # 单步调试
>print var1 # 在调试过程中,我们需要查看当前某个变量值的时候,使用print 命令打印该值
>list # 显示当前调试处的源代码
>info b # 显示当前断点设置情况
当你完成了第一个程序调试之后,你当然会需要更多的命令:关于gdb常用命令及各种调试方法详见 gdb 调试利器 ; 同时,你需要更高效的调试:常用的调试命令都会有单字符的缩写,使用缩写更方便;同时,直接敲回车表示重复执行上一步命令;这在单步调试时非常有用; pstack是一个脚本工具,可显示每个进程的栈跟踪。pstack 命令必须由相应进程的属主或 root 运行。其核心实现就是使用了gdb以及thread apply all bt命令; 语法: $pstrack <program-pid>
示例: $ pstack 4551
Thread 7 (Thread 1084229984 (LWP 4552)):
#0 0x000000302afc63dc in epoll_wait () from /lib64/tls/libc.so.6
#1 0x00000000006f0730 in ub::EPollEx::poll ()
#2 0x00000000006f172a in ub::NetReactor::callback ()
#3 0x00000000006fbbbb in ub::UBTask::CALLBACK ()
#4 0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5 0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6 0x0000000000000000 in ?? ()
strace常用来跟踪进程执行时的系统调用和所接收的信号。在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。 完整程序: strace -o output.txt -T -tt -e trace=all -p 28979
跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。 查看进程正在做什么(实时输出进程执行系统调用的情况): $strace -p <process-pid>
关于strace的详细介绍,详见 strace 跟踪进程中的系统调用 ; 目标文件分析¶nm用来列出目标文件的符号清单。 $nm myProgrammer
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484dc R _IO_stdin_used
w _Jv_RegisterClasses
08049f18 d __CTOR_END__
08049f14 d __CTOR_LIST__
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
080485e0 r __FRAME_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
0804a014 A __bss_start
0804a00c D __data_start
08048490 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
w __gmon_start__
08048482 T __i686.get_pc_thunk.bx
08049f14 d __init_array_end
08049f14 d __init_array_start
08048480 T __libc_csu_fini
08048410 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a014 A _edata
0804a01c A _end
080484bc T _fini
080484d8 R _fp_hw
080482b4 T _init
08048330 T _start
0804a014 b completed.6086
0804a00c W data_start
0804a018 b dtor_idx.6088
080483c0 t frame_dummy
080483e4 T main
U printf@@GLIBC_2.0
这些包含可执行代码的段称为正文段。同样地,数据段包含了不可执行的信息或数据。另一种类型的段,称为 BSS 段,它包含以符号数据开头的块。对于 nm 命令列出的每个符号,它们的值使用十六进制来表示(缺省行为),并且在该符号前面加上了一个表示符号类型的编码字符。 常见的各种编码包括:
可以将目标文件中所包含的不同的部分划分为段。段可以包含可执行代码、符号名称、初始数据值和许多其他类型的数据。有关这些类型的数据的详细信息,可以阅读 UNIX 中 nm 的 man 页面,其中按照该命令输出中的字符编码分别对每种类型进行了描述。 在目标文件阶段,即使是一个简单的 Hello World 程序,其中也包含了大量的细节信息。nm 程序可用于列举符号及其类型和值,但是,要更仔细地研究目标文件中这些命名段的内容,需要使用功能更强大的工具。 其中两种功能强大的工具是 objdump 和 readelf 程序。 Note 关于nm工具的参数说明及更多示例详见 nm 目标文件格式分析 ; ogjdump工具用来显示二进制文件的信息,就是以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。 $objdump -d myprogrammer
a.out: file format elf32-i386
Disassembly of section .init:
080482b4 <_init>:
80482b4: 53 push %ebx
80482b5: 83 ec 08 sub $0x8,%esp
80482b8: e8 00 00 00 00 call 80482bd <_init+0x9>
80482bd: 5b pop %ebx
80482be: 81 c3 37 1d 00 00 add $0x1d37,%ebx
80482c4: 8b 83 fc ff ff ff mov -0x4(%ebx),%eax
80482ca: 85 c0 test %eax,%eax
80482cc: 74 05 je 80482d3 <_init+0x1f>
80482ce: e8 3d 00 00 00 call 8048310 <__gmon_start__@plt>
80482d3: e8 e8 00 00 00 call 80483c0 <frame_dummy>
80482d8: e8 b3 01 00 00 call 8048490 <__do_global_ctors_aux>
80482dd: 83 c4 08 add $0x8,%esp
80482e0: 5b pop %ebx
80482e1: c3 ret
Disassembly of section .plt:
...
每个可执行代码段将在需要特定的事件时执行,这些事件包括库的初始化和该程序本身主入口点。 对于那些着迷于底层编程细节的程序员来说,这是一个功能非常强大的工具,可用于研究编译器和汇编器的输出。细节信息,比如这段代码中所显示的这些信息,可以揭示有关本地处理器本身运行方式的很多内容。对该处理器制造商提供的技术文档进行深入的研究,您可以收集关于一些有价值的信息,通过这些信息可以深入地了解内部的运行机制,因为功能程序提供了清晰的输出。 Note 关于objdump工具的参数说明及更多示例详见 objdump 二进制文件分析 ; 这个工具和objdump命令提供的功能类似,但是它显示的信息更为具体,并且它不依赖BFD库(BFD库是一个GNU项目,它的目标就是希望通过一种统一的接口来处理不同的目标文件); $readelf -all a.out
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048330
Start of program headers: 52 (bytes into file)
Start of section headers: 4412 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 27
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481cc 0001cc 000050 10 A 6 1 4
[ 6] .dynstr STRTAB 0804821c 00021c 00004c 00 A 0 0 1
[ 7] .gnu.version VERSYM 08048268 000268 00000a 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 08048274 000274 000020 00 A 6 1 4
[ 9] .rel.dyn REL 08048294 000294 000008 08 A 5 0 4
[10] .rel.plt REL 0804829c 00029c 000018 08 A 5 12 4
[11] .init PROGBITS 080482b4 0002b4 00002e 00 AX 0 0 4
[12] .plt PROGBITS 080482f0 0002f0 000040 04 AX 0 0 16
[13] .text PROGBITS 08048330 000330 00018c 00 AX 0 0 16
[14] .fini PROGBITS 080484bc 0004bc 00001a 00 AX 0 0 4
[15] .rodata PROGBITS 080484d8 0004d8 000011 00 A 0 0 4
[16] .eh_frame_hdr PROGBITS 080484ec 0004ec 000034 00 A 0 0 4
[17] .eh_frame PROGBITS 08048520 000520 0000c4 00 A 0 0 4
[18] .ctors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
[19] .dtors PROGBITS 08049f1c 000f1c 000008 00 WA 0 0 4
[20] .jcr PROGBITS 08049f24 000f24 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08049f28 000f28 0000c8 08 WA 6 0 4
[22] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 08049ff4 000ff4 000018 04 WA 0 0 4
[24] .data PROGBITS 0804a00c 00100c 000008 00 WA 0 0 4
[25] .bss NOBITS 0804a014 001014 000008 00 WA 0 0 4
[26] .comment PROGBITS 00000000 001014 00002a 01 MS 0 0 1
[27] .shstrtab STRTAB 00000000 00103e 0000fc 00 0 0 1
[28] .symtab SYMTAB 00000000 0015ec 000410 10 29 45 4
[29] .strtab STRTAB 00000000 0019fc 0001f9 00 0 0 1
...
ELF Header 为该文件中所有段入口显示了详细的摘要。在列举出这些 Header 中的内容之前,您可以看到 Header 的具体数目。在研究一个较大的目标文件时,该信息可能非常有用。 除了所有这些段之外,编译器可以将调试信息放入到目标文件中,并且还可以显示这些信息。输入下面的命令,仔细分析编译器的输出(假设您扮演了调试程序的角色): $readelf --debug-dump a.out | more
调试工具,如 GDB,可以读取这些调试信息,并且当程序在调试器中运行的同时,您可以使用该工具显示更具描述性的标记,而不是对代码进行反汇编时的原始地址值。 Note 关于readelf工具的参数说明及更多示例详见 readelf elf文件格式分析 ; size这个工具用来查看程序运行时各个段的实际内存占用: $size a.out
text data bss dec hex filename
1146 256 8 1410 582 a.out
这个工具用于查看文件的类型; 比如我们在64位机器上发现了一个32位的库,链接不上,这就有问题了: $file a.out
a.out: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
也可以查看Core文件是由哪个程序生成: $file core.22355
显示所有正在使用着指定的file, file system 或者 sockets的进程信息; $fuser -m -u redis-server
redis-server: 11552rce(weber) 22912rce(weber) 25501rce(weber)
使用了-m和-u选项,用来查找所有正在使用redis-server的所有进程的PID以及该进程的OWNER; fuser通常被用在诊断系统的”resource busy”问题。如果你希望kill所有正在使用某一指定的file, file system or sockets的进程的时候,你可以使用-k选项: $fuser –k /path/to/your/filename
以十六进制方式显示文件,只显示文本信息: $xxd a.out
0000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
0000010: 0200 0300 0100 0000 3083 0408 3400 0000 ........0...4...
0000020: 3c11 0000 0000 0000 3400 2000 0900 2800 <.......4. ...(.
0000030: 1e00 1b00 0600 0000 3400 0000 3480 0408 ........4...4...
0000040: 3480 0408 2001 0000 2001 0000 0500 0000 4... ... .......
0000050: 0400 0000 0300 0000 5401 0000 5481 0408 ........T...T...
...
通常使用od命令查看特殊格式的文件内容。通过指定该命令的不同选项可以以十进制、八进制、十六进制和ASCII码来显示文件。 参数说明: -A 指定地址基数,包括:
-t 指定数据的显示格式,主要的参数有:
除了选项c以外的其他选项后面都可以跟一个十进制数n,指定每个显示值所包含的字节数。 说明:od命令系统默认的显示方式是八进制,这也是该命令的名称由来(Octal Dump)。但这不是最有用的显示方式,用ASCII码和十六进制组合的方式能提供更有价值的信息输出。 以十六进制和字符同时显示: $od -Ax -tcx4 a.c
000000 # i n c l u d e < s t d i o .
636e6923 6564756c 74733c20 2e6f6964
000010 h > \n \n v o i d m a i n ( ) \n
0a0a3e68 64696f76 69616d20 0a29286e
000020 { \n \t i n t i = 5 ; \n \t p
69090a7b 6920746e 35203d20 70090a3b
000030 r i n t f ( " h e l l o , % d "
746e6972 68222866 6f6c6c65 2264252c
000040 , i ) ; \n } \n
3b29692c 000a7d0a
000047
以字符方式显示: $od -c a.c
0000000 # i n c l u d e < s t d i o .
0000020 h > \n \n v o i d m a i n ( ) \n
0000040 { \n \t i n t i = 5 ; \n \t p
0000060 r i n t f ( " h e l l o , % d "
0000100 , i ) ; \n } \n
0000107
注:类似命令还有hexdump(十六进制输出) 性能优化¶性能优化的核心是找出系统的瓶颈点,问题找到了,优化的工作也就完成了大半; 这里介绍的性能优化主要从两个层面来介绍:系统层面和程序层面; 分析系统瓶颈¶系统响应变慢,首先得定位大致的问题出在哪里,是IO瓶颈、CPU瓶颈、内存瓶颈还是程序导致的系统问题; 使用top工具能够比较全面的查看我们关注的点: $top
top - 09:14:56 up 264 days, 20:56, 1 user, load average: 0.02, 0.04, 0.00
Tasks: 87 total, 1 running, 86 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.2%st
Mem: 377672k total, 322332k used, 55340k free, 32592k buffers
Swap: 397308k total, 67192k used, 330116k free, 71900k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 2856 656 388 S 0.0 0.2 0:49.40 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 7:15.20 ksoftirqd/0
4 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/
分析内存瓶颈¶查看内存是否存在瓶颈,使用top指令看比较麻烦,而free命令更为直观: [/home/weber#]free
total used free shared buffers cached
Mem: 501820 452028 49792 37064 5056 136732
-/+ buffers/cache: 310240 191580
Swap: 0 0 0
[/home/weber#]top
top - 17:52:17 up 42 days, 7:10, 1 user, load average: 0.02, 0.02, 0.05
Tasks: 80 total, 1 running, 79 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 501820 total, 452548 used, 49272 free, 5144 buffers
KiB Swap: 0 total, 0 used, 0 free. 136988 cached Mem
top工具显示了free工具的第一行所有信息,但真实可用的内存,还需要自己计算才知道; 系统实际可用的内存为free工具输出第二行的free+buffer+cached;也就是第三行的free值191580;关于free命令各个值的详情解读,请参考这篇文章 free 查询可用内存 ; 如果是因为缺少内存,系统响应变慢很明显,因为这使得系统不停的做换入换出的工作; 进一步的监视内存使用情况,可使用vmstat工具,实时动态监视操作系统的内存和虚拟内存的动态变化。 参考: vmstat 监视内存使用情况 ; 分析IO瓶颈¶如果IO存在性能瓶颈,top工具中的%wa会偏高; 进一步分析使用iostat工具: /root$iostat -d -x -k 1 1
Linux 2.6.32-279.el6.x86_64 (colin) 07/16/2014 _x86_64_ (4 CPU)
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.02 7.25 0.04 1.90 0.74 35.47 37.15 0.04 19.13 5.58 1.09
dm-0 0.00 0.00 0.04 3.05 0.28 12.18 8.07 0.65 209.01 1.11 0.34
dm-1 0.00 0.00 0.02 5.82 0.46 23.26 8.13 0.43 74.33 1.30 0.76
dm-2 0.00 0.00 0.00 0.01 0.00 0.02 8.00 0.00 5.41 3.28 0.00
更多参数说明请参考 iostat 监视I/O子系统 ; 分析进程调用¶通过top等工具发现系统性能问题是由某个进程导致的之后,接下来我们就需要分析这个进程;继续 查询问题在哪; 这里我们有两个好用的工具: pstack和pstrace pstack用来跟踪进程栈,这个命令在排查进程问题时非常有用,比如我们发现一个服务一直处于work状态(如假死状态,好似死循环),使用这个命令就能轻松定位问题所在;可以在一段时间内,多执行几次pstack,若发现代码栈总是停在同一个位置,那个位置就需要重点关注,很可能就是出问题的地方; 示例:查看bash程序进程栈: /opt/app/tdev1$ps -fe| grep bash
tdev1 7013 7012 0 19:42 pts/1 00:00:00 -bash
tdev1 11402 11401 0 20:31 pts/2 00:00:00 -bash
tdev1 11474 11402 0 20:32 pts/2 00:00:00 grep bash
/opt/app/tdev1$pstack 7013
#0 0x00000039958c5620 in __read_nocancel () from /lib64/libc.so.6
#1 0x000000000047dafe in rl_getc ()
#2 0x000000000047def6 in rl_read_key ()
#3 0x000000000046d0f5 in readline_internal_char ()
#4 0x000000000046d4e5 in readline ()
#5 0x00000000004213cf in ?? ()
#6 0x000000000041d685 in ?? ()
#7 0x000000000041e89e in ?? ()
#8 0x00000000004218dc in yyparse ()
#9 0x000000000041b507 in parse_command ()
#10 0x000000000041b5c6 in read_command ()
#11 0x000000000041b74e in reader_loop ()
#12 0x000000000041b2aa in main ()
而strace用来跟踪进程中的系统调用;这个工具能够动态的跟踪进程执行时的系统调用和所接收的信号。是一个非常有效的检测、指导和调试工具。系统管理员可以通过该命令容易地解决程序问题。 参考: strace 跟踪进程中的系统调用 ; 优化程序代码¶优化自己开发的程序,建议采用以下准则: 1. 二八法则:在任何一组东西中,最重要的只占其中一小部分,约20%,其余80%的尽管是多数,却是次要的;在优化实践中,我们将精力集中在优化那20%最耗时的代码上,整体性能将有显著的提升;这个很好理解。函数A虽然代码量大,但在一次正常执行流程中,只调用了一次。而另一个函数B代码量比A小很多,但被调用了1000次。显然,我们更应关注B的优化。
2. 编完代码,再优化;编码的时候总是考虑最佳性能未必总是好的;在强调最佳性能的编码方式的同时,可能就损失了代码的可读性和开发效率;
关于gprof的使用案例,请参考 [f1] ; 其它工具¶调试内存泄漏的工具valgrind,感兴趣的朋友可以google了解; OProfile: Linux 平台上的一个功能强大的性能分析工具,使用参考 [f2] ; 除了上面介绍的工具,还有一些比较全面的性能分析工具,比如sar(Linux系统上默认不安装,需要手动安装下); 将sar的常驻监控工具打开后,能够收集比较全面的性能分析数据;[f3] 关于sar的使用,参考 sar 找出系统瓶颈的利器 ;
工具参考篇¶gdb 调试利器¶GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c++程序员,gdb是必不可少的工具; 启动gdb¶对C/C++程序的调试,需要在编译前就加上-g选项: $g++ -g hello.cpp -o hello
调试可执行文件: $gdb <program>
program也就是你的执行文件,一般在当前目录下。 调试core文件(core是程序非法执行后core dump后产生的文件): $gdb <program> <core dump file>
$gdb program core.11127
调试服务程序: $gdb <program> <PID>
$gdb hello 11127
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。 gdb交互命令¶启动gdb后,进入到交互模式,通过以下命令完成对程序的调试;注意高频使用的命令一般都会有缩写,熟练使用这些缩写命令能提高调试的效率;
Note 交互模式下直接回车的作用是重复上一指令,对于单步调试非常方便; ldd 查看程序依赖库¶
示例:查看test程序运行所依赖的库: /opt/app/todeav1/test$ldd test
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00000039a7e00000)
libm.so.6 => /lib64/libm.so.6 (0x0000003996400000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000039a5600000)
libc.so.6 => /lib64/libc.so.6 (0x0000003995800000)
/lib64/ld-linux-x86-64.so.2 (0x0000003995400000)
通过上面的信息,我们可以得到以下几个信息:
如果依赖的某个库找不到,通过这个命令可以迅速定位问题所在; Note 原理: ldd不是个可执行程式,而只是个shell脚本; ldd显示可执行模块的dependency的工作原理,其实质是通过ld-linux.so(elf动态库的装载器)来实现的。ld-linux.so模块会先于executable模块程式工作,并获得控制权,因此当上述的那些环境变量被设置时,ld-linux.so选择了显示可执行模块的dependency。 lsof 一切皆文件¶lsof(list open files)是一个查看当前系统文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,该文件描述符提供了大量关于这个应用程序本身的信息。 lsof打开的文件可以是:
命令参数¶
使用实例¶$lsof| more
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 253,0 4096 2 /
init 1 root rtd DIR 253,0 4096 2 /
init 1 root txt REG 253,0 150352 1310795 /sbin/init
init 1 root mem REG 253,0 65928 5505054 /lib64/libnss_files-2.12.so
init 1 root mem REG 253,0 1918016 5521405 /lib64/libc-2.12.so
init 1 root mem REG 253,0 93224 5521440 /lib64/libgcc_s-4.4.6-20120305.so.1
init 1 root mem REG 253,0 47064 5521407 /lib64/librt-2.12.so
init 1 root mem REG 253,0 145720 5521406 /lib64/libpthread-2.12.so
...
说明: lsof输出各列信息的意义如下:
$lsof /bin/bash
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld_sa 2169 root txt REG 253,0 938736 4587562 /bin/bash
ksmtuned 2334 root txt REG 253,0 938736 4587562 /bin/bash
bash 20121 root txt REG 253,0 938736 4587562 /bin/bash
$lsof -u username
-u 选项,u是user的缩写
$lsof -c mysql
-c 选项将会列出所有以mysql这个进程开头的程序的文件,其实你也可以写成 lsof | grep mysql, 但是第一种方法明显比第二种方法要少打几个字符; $lsof -u test -c mysql
$lsof -p 11968
$lsof -i
$lsof -i tcp
$lsof -n -i tcp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
svnserve 11552 weber 3u IPv4 3799399 0t0 TCP *:svn (LISTEN)
redis-ser 25501 weber 4u IPv4 113150 0t0 TCP 127.0.0.1:6379 (LISTEN)
$lsof -i :3306
$lsof -a -u test -i
$lsof -d description(like 2)
示例: $lsof -d 3 | grep PARSER1
tail 6499 tde 3r REG 253,3 4514722 417798 /opt/applog/open/log/HOSTPARSER1_ERROR_141217.log.001
说明: 0表示标准输入,1表示标准输出,2表示标准错误,从而可知:所以大多数应用程序所打开的文件的 FD 都是从 3 开始 $lsof -i 4 -a -p 1234
lsof -i @nf5260i5-td:20,21,80 -r 3
ps 进程查看器¶Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。 要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等。总之大部分信息都是可以通过执行该命令得到的。 ps 为我们提供了进程的一次性的查看,它所提供的查看结果并不动态连续的;如果想对进程时间监控,应该用 top linux下的任务管理器 工具。 注:kill 命令用于杀死进程。 linux上进程有5种状态:
ps工具标识进程的5种状态码:
命令参数¶
输出列的含义¶
使用实例¶[root@localhost test6]# ps -A
PID TTY TIME CMD
1 ? 00:00:00 init
2 ? 00:00:01 migration/0
3 ? 00:00:00 ksoftirqd/0
4 ? 00:00:01 migration/1
5 ? 00:00:00 ksoftirqd/1
6 ? 00:29:57 events/0
7 ? 00:00:00 events/1
8 ? 00:00:00 khelper
49 ? 00:00:00 kthread
54 ? 00:00:00 kblockd/0
55 ? 00:00:00 kblockd/1
56 ? 00:00:00 kacpid
217 ? 00:00:00 cqueue/0
……省略部分结果
[root@localhost test6]# ps -u root
PID TTY TIME CMD
1 ? 00:00:00 init
2 ? 00:00:01 migration/0
3 ? 00:00:00 ksoftirqd/0
4 ? 00:00:01 migration/1
5 ? 00:00:00 ksoftirqd/1
6 ? 00:29:57 events/0
7 ? 00:00:00 events/1
8 ? 00:00:00 khelper
49 ? 00:00:00 kthread
54 ? 00:00:00 kblockd/0
55 ? 00:00:00 kblockd/1
56 ? 00:00:00 kacpid
……省略部分结果
[root@localhost test6]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Nov02 ? 00:00:00 init [3]
root 2 1 0 Nov02 ? 00:00:01 [migration/0]
root 3 1 0 Nov02 ? 00:00:00 [ksoftirqd/0]
root 4 1 0 Nov02 ? 00:00:01 [migration/1]
root 5 1 0 Nov02 ? 00:00:00 [ksoftirqd/1]
root 6 1 0 Nov02 ? 00:29:57 [events/0]
root 7 1 0 Nov02 ? 00:00:00 [events/1]
root 8 1 0 Nov02 ? 00:00:00 [khelper]
root 49 1 0 Nov02 ? 00:00:00 [kthread]
root 54 49 0 Nov02 ? 00:00:00 [kblockd/0]
root 55 49 0 Nov02 ? 00:00:00 [kblockd/1]
root 56 49 0 Nov02 ? 00:00:00 [kacpid]
[root@localhost test6]# ps -ef|grep ssh
root 2720 1 0 Nov02 ? 00:00:00 /usr/sbin/sshd
root 17394 2720 0 14:58 ? 00:00:00 sshd: root@pts/0
root 17465 17398 0 15:57 pts/0 00:00:00 grep ssh
[root@localhost test6]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 17398 17394 0 75 0 - 16543 wait pts/0 00:00:00 bash
4 R 0 17469 17398 0 77 0 - 15877 - pts/0 00:00:00 ps
[root@localhost test6]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 10368 676 ? Ss Nov02 0:00 init [3]
root 2 0.0 0.0 0 0 ? S< Nov02 0:01 [migration/0]
root 3 0.0 0.0 0 0 ? SN Nov02 0:00 [ksoftirqd/0]
root 4 0.0 0.0 0 0 ? S< Nov02 0:01 [migration/1]
root 5 0.0 0.0 0 0 ? SN Nov02 0:00 [ksoftirqd/1]
root 6 0.0 0.0 0 0 ? S< Nov02 29:57 [events/0]
root 7 0.0 0.0 0 0 ? S< Nov02 0:00 [events/1]
root 8 0.0 0.0 0 0 ? S< Nov02 0:00 [khelper]
root 49 0.0 0.0 0 0 ? S< Nov02 0:00 [kthread]
root 54 0.0 0.0 0 0 ? S< Nov02 0:00 [kblockd/0]
root 55 0.0 0.0 0 0 ? S< Nov02 0:00 [kblockd/1]
root 56 0.0 0.0 0 0 ? S< Nov02 0:00 [kacpid]
pstack 跟踪进程栈¶此命令可显示每个进程的栈跟踪。pstack 命令必须由相应进程的属主或 root 运行。可以使用 pstack 来确定进程挂起的位置。此命令允许使用的唯一选项是要检查的进程的 PID。请参见 proc(1) 手册页。 这个命令在排查进程问题时非常有用,比如我们发现一个服务一直处于work状态(如假死状态,好似死循环),使用这个命令就能轻松定位问题所在;可以在一段时间内,多执行几次pstack,若发现代码栈总是停在同一个位置,那个位置就需要重点关注,很可能就是出问题的地方; 示例:查看bash程序进程栈: /opt/app/tdev1$ps -fe| grep bash
tdev1 7013 7012 0 19:42 pts/1 00:00:00 -bash
tdev1 11402 11401 0 20:31 pts/2 00:00:00 -bash
tdev1 11474 11402 0 20:32 pts/2 00:00:00 grep bash
/opt/app/tdev1$pstack 7013
#0 0x00000039958c5620 in __read_nocancel () from /lib64/libc.so.6
#1 0x000000000047dafe in rl_getc ()
#2 0x000000000047def6 in rl_read_key ()
#3 0x000000000046d0f5 in readline_internal_char ()
#4 0x000000000046d4e5 in readline ()
#5 0x00000000004213cf in ?? ()
#6 0x000000000041d685 in ?? ()
#7 0x000000000041e89e in ?? ()
#8 0x00000000004218dc in yyparse ()
#9 0x000000000041b507 in parse_command ()
#10 0x000000000041b5c6 in read_command ()
#11 0x000000000041b74e in reader_loop ()
#12 0x000000000041b2aa in main ()
strace 跟踪进程中的系统调用¶strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。 输出参数含义¶每一行都是一条系统调用,等号左边是系统调用的函数名及其参数,右边是该调用的返回值。 strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。 $strace cat /dev/null
execve("/bin/cat", ["cat", "/dev/null"], [/* 22 vars */]) = 0
brk(0) = 0xab1000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f29379a7000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
...
参数¶-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-a column
设置返回值的输出位置.默认 为40.
-e expr
指定一个表达式,用来控制如何跟踪.格式如下:
[qualifier=][!]value1[,value2]...
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\\.
-e trace=set
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=file
只跟踪有关文件操作的系统调用.
-e trace=process
只跟踪有关进程控制的系统调用.
-e trace=network
跟踪与网络有关的所有系统调用.
-e strace=signal
跟踪所有与系统信号有关的 系统调用
-e trace=ipc
跟踪所有与进程通讯有关的系统调用
-e abbrev=set
设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.
-e raw=set
将指 定的系统调用的参数以十六进制显示.
-e signal=set
指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.
-e read=set
输出从指定文件中读出 的数据.例如:
-e read=3,5
-e write=set
输出写入到指定文件中的数据.
-o filename
将strace的输出写入文件filename
-p pid
跟踪指定的进程pid.
-s strsize
指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username
以username 的UID和GID执行被跟踪的命令
ipcs 查询进程间通信状态¶ipcs是Linux下显示进程间通信设施状态的工具。可以显示消息队列、共享内存和信号量的信息。对于程序员非常有用,普通的系统管理员一般用不到此指令。 IPC资源查询¶$ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 229376 weber 600 1
------ Message Queues --------
key msqid owner perms used-bytes messages
分别查询IPC资源: $ipcs -m 查看系统使用的IPC共享内存资源
$ipcs -q 查看系统使用的IPC队列资源
$ipcs -s 查看系统使用的IPC信号量资源
示例:有个IPCKEY(51036),需要查询其是否被占用;
系统IPC参数查询¶ipcs -l
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 4194303
max total shared memory (kbytes) = 1073741824
min seg size (bytes) = 1
------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767
------ Messages: Limits --------
max queues system wide = 2048
max size of message (bytes) = 524288
default max size of queue (bytes) = 5242880
以上输出显示,目前这个系统的允许的最大内存为1073741824kb;最大可使用128个信号量,每个消息的最大长度为524288bytes; 修改IPC系统参数¶以linux系统为例,在root用户下修改/etc/sysctl.conf 文件,保存后使用sysctl -p生效: $cat /etc/sysctl.conf
# 一个消息的最大长度
kernel.msgmax = 524288
# 一个消息队列上的最大字节数
# 524288*10
kernel.msgmnb = 5242880
#最大消息队列的个数
kernel.msgmni=2048
#一个共享内存区的最大字节数
kernel.shmmax = 17179869184
#系统范围内最大共享内存标识数
kernel.shmmni=4096
#每个信号灯集的最大信号灯数 系统范围内最大信号灯数 每个信号灯支持的最大操作数 系统范围内最大信号灯集数
#此参数为系统默认,可以不用修改
#kernel.sem = <semmsl> <semmni>*<semmsl> <semopm> <semmni>
kernel.sem = 250 32000 32 128
显示输入不带标志的 ipcs:的输出: $ipcs
IPC status from /dev/mem as of Mon Aug 14 15:03:46 1989
T ID KEY MODE OWNER GROUP
Message Queues:
q 0 0x00010381 -Rrw-rw-rw- root system
q 65537 0x00010307 -Rrw-rw-rw- root system
q 65538 0x00010311 -Rrw-rw-rw- root system
q 65539 0x0001032f -Rrw-rw-rw- root system
q 65540 0x0001031b -Rrw-rw-rw- root system
q 65541 0x00010339--rw-rw-rw- root system
q 6 0x0002fe03 -Rrw-rw-rw- root system
Shared Memory:
m 65537 0x00000000 DCrw------- root system
m 720898 0x00010300 -Crw-rw-rw- root system
m 65539 0x00000000 DCrw------- root system
Semaphores:
s 131072 0x4d02086a --ra-ra---- root system
s 65537 0x00000000 --ra------- root system
s 1310722 0x000133d0 --ra------- 7003 30720
清除IPC资源¶使用ipcrm 命令来清除IPC资源:这个命令同时会将与ipc对象相关联的数据也一起移除。当然,只有root用户,或者ipc对象的创建者才有这项权利; ipcrm用法: ipcrm -M shmkey 移除用shmkey创建的共享内存段
ipcrm -m shmid 移除用shmid标识的共享内存段
ipcrm -Q msgkey 移除用msqkey创建的消息队列
ipcrm -q msqid 移除用msqid标识的消息队列
ipcrm -S semkey 移除用semkey创建的信号
ipcrm -s semid 移除用semid标识的信号
清除当前用户创建的所有的IPC资源: ipcs -q | awk '{ print "ipcrm -q "$2}' | sh > /dev/null 2>&1;
ipcs -m | awk '{ print "ipcrm -m "$2}' | sh > /dev/null 2>&1;
ipcs -s | awk '{ print "ipcrm -s "$2}' | sh > /dev/null 2>&1;
综合应用¶
top linux下的任务管理器¶top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止.比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序;而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定。 $top
top - 09:14:56 up 264 days, 20:56, 1 user, load average: 0.02, 0.04, 0.00
Tasks: 87 total, 1 running, 86 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.2%st
Mem: 377672k total, 322332k used, 55340k free, 32592k buffers
Swap: 397308k total, 67192k used, 330116k free, 71900k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 2856 656 388 S 0.0 0.2 0:49.40 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 7:15.20 ksoftirqd/0
4 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
top命令交互操作指令¶下面列出一些常用的 top命令操作指令
注:强调一下,使用频率最高的是P、T、M,因为通常使用top,我们就想看看是哪些进程最耗cpu资源、占用的内存最多; 注:通过”shift + >”或”shift + <”可以向右或左改变排序列 如果只需要查看内存:可用free命令。只查看uptime信息(第一行),可用uptime命令; 实例¶在top基本视图中,按键盘数字“1”,可监控每个逻辑CPU的状况; [rdtfr@bl685cb4-t ^]$ top
top - 09:10:44 up 20 days, 16:51, 4 users, load average: 3.82, 4.40, 4.40
Tasks: 1201 total, 10 running, 1189 sleeping, 0 stopped, 2 zombie
Cpu0 : 1.3%us, 2.3%sy, 0.0%ni, 96.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 1.3%us, 2.6%sy, 0.0%ni, 96.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 1.0%us, 2.0%sy, 0.0%ni, 92.5%id, 0.0%wa, 0.0%hi, 4.6%si, 0.0%st
Cpu3 : 3.9%us, 7.8%sy, 0.0%ni, 83.2%id, 0.0%wa, 0.0%hi, 5.2%si, 0.0%st
Cpu4 : 4.2%us, 10.4%sy, 0.0%ni, 63.8%id, 0.0%wa, 0.0%hi, 21.5%si, 0.0%st
Cpu5 : 6.8%us, 12.7%sy, 0.0%ni, 80.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu6 : 2.9%us, 7.2%sy, 0.0%ni, 85.3%id, 0.0%wa, 0.0%hi, 4.6%si, 0.0%st
Cpu7 : 6.2%us, 13.0%sy, 0.0%ni, 75.3%id, 0.0%wa, 0.0%hi, 5.5%si, 0.0%st
Mem: 32943888k total, 32834216k used, 109672k free, 642704k buffers
Swap: 35651576k total, 5761928k used, 29889648k free, 16611500k cached
在top基本视图中,按键盘“b”(打开/关闭加亮效果);
命令:top -c [rdtfr@bl685cb4-t ^]$ top -c
top - 09:14:35 up 20 days, 16:55, 4 users, load average: 5.77, 5.01, 4.64
Tasks: 1200 total, 5 running, 1192 sleeping, 0 stopped, 3 zombie
Cpu(s): 4.4%us, 6.0%sy, 0.0%ni, 83.8%id, 0.2%wa, 0.0%hi, 5.5%si, 0.0%st
Mem: 32943888k total, 32842896k used, 100992k free, 591484k buffers
Swap: 35651576k total, 5761808k used, 29889768k free, 16918824k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2013 apache 18 0 403m 88m 5304 S 25.0 0.3 6:37.44 /usr/sbin/httpd
18335 pubtest 22 0 65576 996 728 R 7.8 0.0 0:00.24 netstat -naltp
16499 rdtfare 15 0 13672 2080 824 R 2.6 0.0 0:00.38 top -c
29684 rdtfare 15 0 1164m 837m 14m S 2.3 2.6 148:47.54 ./autodata data1.txt
12976 pubtest 18 0 238m 9000 1932 S 1.6 0.0 439:28.44 tscagent -s TOEV_P
命令:top -p pidid /opt/app/tdv1/config#top -p 17265
top - 09:17:34 up 455 days, 17:55, 2 users, load average: 3.76, 4.56, 4.46
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Cpu(s): 7.8%us, 1.9%sy, 0.0%ni, 89.2%id, 0.0%wa, 0.1%hi, 1.0%si, 0.0%st
Mem: 8175452k total, 8103988k used, 71464k free, 268716k buffers
Swap: 6881272k total, 4275424k used, 2605848k free, 6338184k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
17265 tdv1 15 0 56504 828 632 S 0.0 0.0 195:53.25 redis-server
指定进程信息有多个时,需要结合其它工具将回车替换为,(-p 支持pid,pid,pid语法) 命令:top -p pgrep MULTI_PROCESS | tr “\n” “,” | sed ‘s/,$//’ /opt/app/tdv1$top -p `pgrep java | tr "\\n" "," | sed 's/,$//'`
top - 14:05:31 up 53 days, 2:43, 9 users, load average: 0.29, 0.34, 0.22
Tasks: 3 total, 0 running, 3 sleeping, 0 stopped, 0 zombie
Cpu(s): 5.9%us, 8.2%sy, 0.0%ni, 86.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 66082088k total, 29512860k used, 36569228k free, 756352k buffers
Swap: 32767992k total, 1019900k used, 31748092k free, 15710284k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 27855 rdtfare 20 0 4454m 1.3g 5300 S 0.7 2.0 338:31.37 java
2034 jenkins 20 0 18.3g 5.2g 5284 S 0.3 8.2 56:02.38 java 12156 rdtfare 20 0 4196m 1.2g 12m S 0.3 2.0 86:34.62 java
free 查询可用内存¶free工具用来查看系统可用内存: /opt/app/tdev1$free
total used free shared buffers cached
Mem: 8175320 6159248 2016072 0 310208 5243680
-/+ buffers/cache: 605360 7569960
Swap: 6881272 16196 6865076
解释一下Linux上free命令的输出。 下面是free的运行结果,一共有4行。为了方便说明,我加上了列号。这样可以把free的输出看成一个二维数组FO(Free Output)。例如: FO[2][1] = 24677460
FO[3][2] = 10321516
1 2 3 4 5 6
1 total used free shared buffers cached
2 Mem: 24677460 23276064 1401396 0 870540 12084008
3 -/+ buffers/cache: 10321516 14355944
4 Swap: 25151484 224188 24927296
free的输出一共有四行,第四行为交换区的信息,分别是交换的总量(total),使用量(used)和有多少空闲的交换区(free),这个比较清楚,不说太多。 free输出地第二行和第三行是比较让人迷惑的。这两行都是说明内存使用情况的。第一列是总量(total),第二列是使用量(used),第三列是可用量(free)。 第一行的输出时从操作系统(OS)来看的。也就是说,从OS的角度来看,计算机上一共有: 24677460KB(缺省时free的单位为KB)物理内存,即FO[2][1]; 在这些物理内存中有23276064KB(即FO[2][2])被使用了; 还用1401396KB(即FO[2][3])是可用的; 这里得到第一个等式: FO[2][1] = FO[2][2] + FO[2][3] FO[2][4]表示被几个进程共享的内存的,现在已经deprecated,其值总是0(当然在一些系统上也可能不是0,主要取决于free命令是怎么实现的)。 FO[2][5]表示被OS buffer住的内存。FO[2][6]表示被OS cache的内存。在有些时候buffer和cache这两个词经常混用。不过在一些比较低层的软件里是要区分这两个词的,看老外的洋文: A buffer is something that has yet to be "written" to disk.
A cache is something that has been "read" from the disk and stored for later use.
也就是说buffer是用于存放要输出到disk(块设备)的数据的,而cache是存放从disk上读出的数据。这二者是为了提高IO性能的,并由OS管理。 Linux和其他成熟的操作系统(例如windows),为了提高IO read的性能,总是要多cache一些数据,这也就是为什么FO[2][6](cached memory)比较大,而FO[2][3]比较小的原因。我们可以做一个简单的测试: 释放掉被系统cache占用的数据: echo 3>/proc/sys/vm/drop_caches
第二次读应该比第一次快很多。原来我做过一个BerkeleyDB的读操作,大概要读5G的文件,几千万条记录。在我的环境上,第二次读比第一次大概可以快9倍左右。 free输出的第二行是从一个应用程序的角度看系统内存的使用情况。
因为被系统cache和buffer占用的内存可以被快速回收,所以通常FO[3][3]比FO[2][3]会大很多。 这里还用两个等式: FO[3][2] = FO[2][2] - FO[2][5] - FO[2][6]
FO[3][3] = FO[2][3] + FO[2][5] + FO[2][6]
这二者都不难理解。 free命令由procps.*.rpm提供(在Redhat系列的OS上)。free命令的所有输出值都是从/proc/meminfo中读出的。 在系统上可能有meminfo(2)这个函数,它就是为了解析/proc/meminfo的。procps这个包自己实现了meminfo()这个函数。可以下载一个procps的tar包看看具体实现,现在最新版式3.2.8。 文章出处: http://www.cnblogs.com/coldplayerest/archive/2010/02/20/1669949.html vmstat 监视内存使用情况¶vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可实时动态监视操作系统的虚拟内存、进程、CPU活动。 vmstat的语法¶vmstat [-V] [-n] [delay [count]]
/root$vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
6 0 0 27900472 204216 28188356 0 0 0 9 1 2 11 14 75 0 0
9 0 0 27900380 204228 28188360 0 0 0 13 33312 126221 22 20 58 0 0
2 0 0 27900340 204240 28188364 0 0 0 10 32755 125566 22 20 58 0 0
字段说明¶
iostat 监视I/O子系统¶iostat是I/O statistics(输入/输出统计)的缩写,用来动态监视系统的磁盘操作活动。 命令格式¶iostat[参数][时间][次数] 命令功能¶通过iostat方便查看CPU、网卡、tty设备、磁盘、CD-ROM 等等设备的活动情况, 负载信息。 命令参数¶
工具实例¶/root$iostat
Linux 2.6.32-279.el6.x86_64 (colin) 07/16/2014 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
10.81 0.00 14.11 0.18 0.00 74.90
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 1.95 1.48 70.88 9145160 437100644
dm-0 3.08 0.55 24.34 3392770 150087080
dm-1 5.83 0.93 46.49 5714522 286724168
dm-2 0.01 0.00 0.05 23930 289288
注:如果%iowait的值过高,表示硬盘存在I/O瓶颈,%idle值高,表示CPU较空闲,如果%idle值高但系统响应慢时,有可能是CPU等待分配内存,此时应加大内存容量。%idle值如果持续低于10,那么系统的CPU处理能力相对较低,表明系统中最需要解决的资源是CPU。
备注:如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明I/O 队列太长,io响应太慢,则需要进行必要优化。如果avgqu-sz比较大,也表示有当量io在等待。 /root$iostat 2 3
Linux 2.6.32-279.el6.x86_64 (colin) 07/16/2014 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
10.81 0.00 14.11 0.18 0.00 74.90
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 1.95 1.48 70.88 9145160 437106156
dm-0 3.08 0.55 24.34 3392770 150088376
dm-1 5.83 0.93 46.49 5714522 286728384
dm-2 0.01 0.00 0.05 23930 289288
avg-cpu: %user %nice %system %iowait %steal %idle
22.62 0.00 19.67 0.26 0.00 57.46
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 2.50 0.00 28.00 0 56
dm-0 0.00 0.00 0.00 0 0
dm-1 3.50 0.00 28.00 0 56
dm-2 0.00 0.00 0.00 0 0
avg-cpu: %user %nice %system %iowait %steal %idle
22.69 0.00 19.62 0.00 0.00 57.69
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 0.00 0.00 0.00 0 0
dm-0 0.00 0.00 0.00 0 0
dm-1 0.00 0.00 0.00 0 0
dm-2 0.00 0.00 0.00 0 0
说明:每隔 2秒刷新显示,且显示3次 /root$iostat -d -k 1 1
Linux 2.6.32-279.el6.x86_64 (colin) 07/16/2014 _x86_64_ (4 CPU)
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 1.95 0.74 35.44 4572712 218559410
dm-0 3.08 0.28 12.17 1696513 75045968
dm-1 5.83 0.46 23.25 2857265 143368744
dm-2 0.01 0.00 0.02 11965 144644
这些单位都为Kilobytes。 上面的例子中,我们可以看到磁盘sda以及它的各个分区的统计数据,当时统计的磁盘总TPS是1.95,下面是各个分区的TPS。(因为是瞬间值,所以总TPS并不严格等于各个分区TPS的总和) /root$iostat -d -x -k 1 1
Linux 2.6.32-279.el6.x86_64 (colin) 07/16/2014 _x86_64_ (4 CPU)
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
sda 0.02 7.25 0.04 1.90 0.74 35.47 37.15 0.04 19.13 5.58 1.09
dm-0 0.00 0.00 0.04 3.05 0.28 12.18 8.07 0.65 209.01 1.11 0.34
dm-1 0.00 0.00 0.02 5.82 0.46 23.26 8.13 0.43 74.33 1.30 0.76
dm-2 0.00 0.00 0.00 0.01 0.00 0.02 8.00 0.00 5.41 3.28 0.00
如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。 idle小于70% IO压力就较大了,一般读取速度有较多的wait。 同时可以结合vmstat 查看查看b参数(等待资源的进程数)和wa参数(IO等待所占用的CPU时间的百分比,高过30%时IO压力高)。 另外 await 的参数也要多和 svctm 来参考。差的过高就一定有 IO 的问题。 avgqu-sz 也是个做 IO 调优时需要注意的地方,这个就是直接每次操作的数据的大小,如果次数多,但数据拿的小的话,其实 IO 也会很小。如果数据拿的大,才IO 的数据会高。也可以通过 avgqu-sz × ( r/s or w/s ) = rsec/s or wsec/s。也就是讲,读定速度是这个来决定的。 svctm 一般要小于 await (因为同时等待的请求的等待时间被重复计算了),svctm 的大小一般和磁盘性能有关,CPU/内存的负荷也会对其有影响,请求过多也会间接导致 svctm 的增加。await 的大小一般取决于服务时间(svctm) 以及 I/O 队列的长度和 I/O 请求的发出模式。如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;如果 await 远大于 svctm,说明 I/O 队列太长,应用得到的响应时间变慢,如果响应时间超过了用户可以容许的范围,这时可以考虑更换更快的磁盘,调整内核 elevator 算法,优化应用,或者升级 CPU。 队列长度(avgqu-sz)也可作为衡量系统 I/O 负荷的指标,但由于 avgqu-sz 是按照单位时间的平均值,所以不能反映瞬间的 I/O 洪水。
设备IO操作:总IO(io)/s = r/s(读) +w/s(写) 平均等待时间=单个I/O服务器时间*(1+2+…+请求总数-1)/请求总数 每秒发出的I/0请求很多,但是平均队列就4,表示这些请求比较均匀,大部分处理还是比较及时。 sar 找出系统瓶颈的利器¶sar是System Activity Reporter(系统活动情况报告)的缩写。sar工具将对系统当前的状态进行取样,然后通过计算数据和比例来表达系统的当前运行状态。它的特点是可以连续对系统取样,获得大量的取样数据;取样数据和分析的结果都可以存入文件,所需的负载很小。sar是目前Linux上最为全面的系统性能分析工具之一,可以从14个大方面对系统的活动进行报告,包括文件的读写情况、系统调用的使用情况、串口、CPU效率、内存使用状况、进程活动及IPC有关的活动等,使用也是较为复杂。 sar是查看操作系统报告指标的各种工具中,最为普遍和方便的;它有两种用法;
追溯过去的统计数据¶默认情况下,sar从最近的0点0分开始显示数据;如果想继续查看一天前的报告;可以查看保存在/var/log/sysstat/下的sa日志; 使用sar工具查看: $sar -f /var/log/sysstat/sa28 \| head sar -r -f
/var/log/sysstat/sa28
![]() 查看CPU使用率¶sar -u : 默认情况下显示的cpu使用率等信息就是sar -u; ![]() 可以看到这台机器使用了虚拟化技术,有相应的时间消耗; 各列的指标分别是:
查看平均负载¶sar -q: 查看平均负载 指定-q后,就能查看运行队列中的进程数、系统上的进程大小、平均负载等;与其它命令相比,它能查看各项指标随时间变化的情况;
![]() 查看内存使用状况¶sar -r: 指定-r之后,可查看物理内存使用状况; ![]()
查看页面交换发生状况¶sar -W:查看页面交换发生状况 页面发生交换时,服务器的吞吐量会大幅下降;服务器状况不良时,如果怀疑因为内存不足而导致了页面交换的发生,可以使用这个命令来确认是否发生了大量的交换; ![]()
要判断系统瓶颈问题,有时需几个 sar 命令选项结合起来;
安装¶
sar参数说明¶
readelf elf文件格式分析¶这个工具和objdump命令提供的功能类似,但是它显示的信息更为具体,并且它不依赖BFD库(BFD库是一个GNU项目,它的目标就是希望通过一种统一的接口来处理不同的目标文件);
ELF文件有三种类型:
参数说明¶
示例¶想知道一个应用程序的可运行的架构平台: $readelf -h main| grep Machine
-h选项将显示文件头的概要信息,从里面可以看到,有很多有用的信息: $readelf -h main
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2 s complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400790
Start of program headers: 64 (bytes into file)
Start of section headers: 5224 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 8
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 26
一个编译好的应用程序,想知道其编译时是否使用了-g选项(加入调试信息): $readelf -S main| grep debug
用-S选项是显示所有段信息;如果编译时使用了-g选项,则会有debug段; 查看.o文件是否编入了调试信息(编译的时候是否加了-g): $readelf -S Shpos.o | grep debug
完整输出¶readelf输出的完整内容: $readelf -all a.out
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048330
Start of program headers: 52 (bytes into file)
Start of section headers: 4412 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 27
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481cc 0001cc 000050 10 A 6 1 4
[ 6] .dynstr STRTAB 0804821c 00021c 00004c 00 A 0 0 1
[ 7] .gnu.version VERSYM 08048268 000268 00000a 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 08048274 000274 000020 00 A 6 1 4
[ 9] .rel.dyn REL 08048294 000294 000008 08 A 5 0 4
[10] .rel.plt REL 0804829c 00029c 000018 08 A 5 12 4
[11] .init PROGBITS 080482b4 0002b4 00002e 00 AX 0 0 4
[12] .plt PROGBITS 080482f0 0002f0 000040 04 AX 0 0 16
[13] .text PROGBITS 08048330 000330 00018c 00 AX 0 0 16
[14] .fini PROGBITS 080484bc 0004bc 00001a 00 AX 0 0 4
[15] .rodata PROGBITS 080484d8 0004d8 000011 00 A 0 0 4
[16] .eh_frame_hdr PROGBITS 080484ec 0004ec 000034 00 A 0 0 4
[17] .eh_frame PROGBITS 08048520 000520 0000c4 00 A 0 0 4
[18] .ctors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
[19] .dtors PROGBITS 08049f1c 000f1c 000008 00 WA 0 0 4
[20] .jcr PROGBITS 08049f24 000f24 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08049f28 000f28 0000c8 08 WA 6 0 4
[22] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 08049ff4 000ff4 000018 04 WA 0 0 4
[24] .data PROGBITS 0804a00c 00100c 000008 00 WA 0 0 4
[25] .bss NOBITS 0804a014 001014 000008 00 WA 0 0 4
[26] .comment PROGBITS 00000000 001014 00002a 01 MS 0 0 1
[27] .shstrtab STRTAB 00000000 00103e 0000fc 00 0 0 1
[28] .symtab SYMTAB 00000000 0015ec 000410 10 29 45 4
[29] .strtab STRTAB 00000000 0019fc 0001f9 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x005e4 0x005e4 R E 0x1000
LOAD 0x000f14 0x08049f14 0x08049f14 0x00100 0x00108 RW 0x1000
DYNAMIC 0x000f28 0x08049f28 0x08049f28 0x000c8 0x000c8 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x0004ec 0x080484ec 0x080484ec 0x00034 0x00034 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
GNU_RELRO 0x000f14 0x08049f14 0x08049f14 0x000ec 0x000ec R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .ctors .dtors .jcr .dynamic .got
Dynamic section at offset 0xf28 contains 20 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x80482b4
0x0000000d (FINI) 0x80484bc
0x6ffffef5 (GNU_HASH) 0x80481ac
0x00000005 (STRTAB) 0x804821c
0x00000006 (SYMTAB) 0x80481cc
0x0000000a (STRSZ) 76 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x8049ff4
0x00000002 (PLTRELSZ) 24 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x804829c
0x00000011 (REL) 0x8048294
0x00000012 (RELSZ) 8 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x8048274
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x8048268
0x00000000 (NULL) 0x0
Relocation section '.rel.dyn' at offset 0x294 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049ff0 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x29c contains 3 entries:
Offset Info Type Sym.Value Sym. Name
0804a000 00000107 R_386_JUMP_SLOT 00000000 printf
0804a004 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__
0804a008 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main
There are no unwind sections in this file.
Symbol table '.dynsym' contains 5 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.0 (2)
2: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2)
4: 080484dc 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
Symbol table '.symtab' contains 65 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 08048154 0 SECTION LOCAL DEFAULT 1
2: 08048168 0 SECTION LOCAL DEFAULT 2
3: 08048188 0 SECTION LOCAL DEFAULT 3
4: 080481ac 0 SECTION LOCAL DEFAULT 4
5: 080481cc 0 SECTION LOCAL DEFAULT 5
6: 0804821c 0 SECTION LOCAL DEFAULT 6
7: 08048268 0 SECTION LOCAL DEFAULT 7
8: 08048274 0 SECTION LOCAL DEFAULT 8
9: 08048294 0 SECTION LOCAL DEFAULT 9
10: 0804829c 0 SECTION LOCAL DEFAULT 10
11: 080482b4 0 SECTION LOCAL DEFAULT 11
12: 080482f0 0 SECTION LOCAL DEFAULT 12
13: 08048330 0 SECTION LOCAL DEFAULT 13
14: 080484bc 0 SECTION LOCAL DEFAULT 14
15: 080484d8 0 SECTION LOCAL DEFAULT 15
16: 080484ec 0 SECTION LOCAL DEFAULT 16
17: 08048520 0 SECTION LOCAL DEFAULT 17
18: 08049f14 0 SECTION LOCAL DEFAULT 18
19: 08049f1c 0 SECTION LOCAL DEFAULT 19
20: 08049f24 0 SECTION LOCAL DEFAULT 20
21: 08049f28 0 SECTION LOCAL DEFAULT 21
22: 08049ff0 0 SECTION LOCAL DEFAULT 22
23: 08049ff4 0 SECTION LOCAL DEFAULT 23
24: 0804a00c 0 SECTION LOCAL DEFAULT 24
25: 0804a014 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 SECTION LOCAL DEFAULT 26
27: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
28: 08049f14 0 OBJECT LOCAL DEFAULT 18 __CTOR_LIST__
29: 08049f1c 0 OBJECT LOCAL DEFAULT 19 __DTOR_LIST__
30: 08049f24 0 OBJECT LOCAL DEFAULT 20 __JCR_LIST__
31: 08048360 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
32: 0804a014 1 OBJECT LOCAL DEFAULT 25 completed.6086
33: 0804a018 4 OBJECT LOCAL DEFAULT 25 dtor_idx.6088
34: 080483c0 0 FUNC LOCAL DEFAULT 13 frame_dummy
35: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 08049f18 0 OBJECT LOCAL DEFAULT 18 __CTOR_END__
37: 080485e0 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
38: 08049f24 0 OBJECT LOCAL DEFAULT 20 __JCR_END__
39: 08048490 0 FUNC LOCAL DEFAULT 13 __do_global_ctors_aux
40: 00000000 0 FILE LOCAL DEFAULT ABS a.c
41: 08049f14 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
42: 08049f28 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
43: 08049f14 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
44: 08049ff4 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_
45: 08048480 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
46: 08048482 0 FUNC GLOBAL HIDDEN 13 __i686.get_pc_thunk.bx
47: 0804a00c 0 NOTYPE WEAK DEFAULT 24 data_start
48: 00000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.0
49: 0804a014 0 NOTYPE GLOBAL DEFAULT ABS _edata
50: 080484bc 0 FUNC GLOBAL DEFAULT 14 _fini
51: 08049f20 0 OBJECT GLOBAL HIDDEN 19 __DTOR_END__
52: 0804a00c 0 NOTYPE GLOBAL DEFAULT 24 __data_start
53: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
54: 0804a010 0 OBJECT GLOBAL HIDDEN 24 __dso_handle
55: 080484dc 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
56: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
57: 08048410 97 FUNC GLOBAL DEFAULT 13 __libc_csu_init
58: 0804a01c 0 NOTYPE GLOBAL DEFAULT ABS _end
59: 08048330 0 FUNC GLOBAL DEFAULT 13 _start
60: 080484d8 4 OBJECT GLOBAL DEFAULT 15 _fp_hw
61: 0804a014 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
62: 080483e4 40 FUNC GLOBAL DEFAULT 13 main
63: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
64: 080482b4 0 FUNC GLOBAL DEFAULT 11 _init
Histogram for `.gnu.hash' bucket list length (total of 2 buckets):
Length Number % of total Coverage
0 1 ( 50.0%)
1 1 ( 50.0%) 100.0%
Version symbols section '.gnu.version' contains 5 entries:
Addr: 0000000008048268 Offset: 0x000268 Link: 5 (.dynsym)
000: 0 (*local*) 2 (GLIBC_2.0) 0 (*local*) 2 (GLIBC_2.0)
004: 1 (*global*)
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x0000000008048274 Offset: 0x000274 Link: 6 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 1
0x0010: Name: GLIBC_2.0 Flags: none Version: 2
Notes at offset 0x00000168 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 2.6.15
Notes at offset 0x00000188 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 17fb9651029b6a8543bfafec9eea23bd16454e65
关于ELF文件格式的参考:http://www.cnblogs.com/xmphoenix/archive/2011/10/23/2221879.html objdump 二进制文件分析¶objdump工具用来显示二进制文件的信息,就是以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。 常用参数说明¶
示例¶查看本机目标结构(使用大端还是小端存储): $objdump -i
反汇编程序: $objdump -d main.o
显示符号表入口: $objdump -t main.o
希望显示可用的简洁帮助信息,直接输入objdump即可;(objdump -H) nm 目标文件格式分析¶nm 命令显示关于指定 File 中符号的信息,文件可以是对象文件、可执行文件或对象文件库。如果文件没有包含符号信息,nm 命令报告该情况,但不把它解释为出错条件。 nm 命令缺省情况下报告十进制符号表示法下的数字值。 $nm myProgrammer
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484dc R _IO_stdin_used
w _Jv_RegisterClasses
08049f18 d __CTOR_END__
08049f14 d __CTOR_LIST__
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
080485e0 r __FRAME_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
0804a014 A __bss_start
0804a00c D __data_start
08048490 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
w __gmon_start__
08048482 T __i686.get_pc_thunk.bx
08049f14 d __init_array_end
08049f14 d __init_array_start
08048480 T __libc_csu_fini
08048410 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a014 A _edata
0804a01c A _end
080484bc T _fini
080484d8 R _fp_hw
080482b4 T _init
08048330 T _start
0804a014 b completed.6086
0804a00c W data_start
0804a018 b dtor_idx.6088
080483c0 t frame_dummy
080483e4 T main
U printf@@GLIBC_2.0
这些包含可执行代码的段称为正文段。同样地,数据段包含了不可执行的信息或数据。另一种类型的段,称为 BSS 段,它包含以符号数据开头的块。对于 nm 命令列出的每个符号,它们的值使用十六进制来表示(缺省行为),并且在该符号前面加上了一个表示符号类型的编码字符。 可以将目标文件中所包含的不同的部分划分为段。段可以包含可执行代码、符号名称、初始数据值和许多其他类型的数据。有关这些类型的数据的详细信息,可以阅读 UNIX 中 nm 的 man 页面,其中按照该命令输出中的字符编码分别对每种类型进行了描述。 选项说明¶
符号说明¶对于每一个符号来说,其类型如果是小写的,则表明该符号是local的;大写则表明该符号是global(external)的。
库或对象名 如果您指定了 -A 选项,则 nm 命令只报告与该文件有关的或者库或者对象名。 示例¶
有时会碰到一个编译了但没有链接的代码,那是因为它缺失了标识符;这种情况,可以用nm和objdump、readelf命令来查看程序的符号表;所有这些命令做的工作基本一样; 比如连接器报错有未定义的标识符;大多数情况下,会发生在库的缺失或企图链接一个错误版本的库的时候;浏览目标代码来寻找一个特殊标识符的引用: nm -uCA *.o | grep foo
-u选项限制了每个目标文件中未定义标识符的输出。-A选项用于显示每个标识符的文件名信息;对于C++代码,常用的还有-C选项,它也为解码这些标识符; Note objdump、readld命令可以完成同样的任务。等效命令为: $objdump -t $readelf -s
size 查看程序内存映像大小¶作用:查看程序被映射到内存中的映像所占用的大小信息。 程序映射到内存中,从低地址到高地址依次为下列段:
另外, 在高地址还储存了命令行参数及环境变量. 因为内存程序映像中的各段可能位于不同的地址空间中, 它们不一定位于连续的内存块中. 操作系统将程序映像映射到地址空间时, 通常将内存程序映像划分为大小相同的块(也就是page, 页). 只有该页被引用时, 它才被加载到内存中. 不过对于程序员来说, 可以视内存程序映像在逻辑上是连续的. /opt/app/todeav1/colin/tests#size main
text data bss dec hex filename
1259 540 16 1815 717 main
关于程序内存映像,这篇文章讲的很好:http://blog.chinaunix.net/uid-9012903-id-2011435.html wget 文件下载¶Linux系统中的wget是一个下载文件的工具,它用在命令行下。对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器。wget支持HTTP,HTTPS和FTP协议,可以使用HTTP代理。 wget 可以跟踪HTML页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构。这又常被称作”递归下载”。在递归下载的时候,wget 遵循Robot Exclusion标准(/robots.txt). wget可以在下载的同时,将链接转换成指向本地文件,以方便离线浏览。 wget 非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性.如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。 命令格式¶wget [参数] [URL地址] 命令参数:¶
–sslcertfile=FILE 可选客户端证书 –sslcertkey=KEYFILE 可选客户端证书的KEYFILE –egd-file=FILE 指定EGD socket的文件名
wget -S –spider url 不下载只显示过程 使用实例¶$wget http://www.minjieren.com/wordpress-3.1-zh_CN.zip
说明:以上例子从网络下载一个文件并保存在当前目录,在下载的过程中会显示进度条,包含(下载完成百分比,已经下载的字节,当前下载速度,剩余下载时间)。 $wget -O wordpress.zip http://www.minjieren.com/download.aspx?id=1080
wget默认会以最后一个符合”/”的后面的字符来命令,对于动态链接的下载通常文件名会不正确。 $wget --limit-rate=300k http://www.minjieren.com/wordpress-3.1-zh_CN.zip
当你执行wget的时候,它默认会占用全部可能的宽带下载。但是当你准备下载一个大文件,而你还需要下载其它文件时就有必要限速了。 $wget -c http://www.minjieren.com/wordpress-3.1-zh_CN.zip
使用wget -c重新启动下载中断的文件,对于我们下载大文件时突然由于网络等原因中断非常有帮助,我们可以继续接着下载而不是重新下载一个文件。需要继续中断的下载时可以使用-c参数。 $wget -b http://www.minjieren.com/wordpress-3.1-zh_CN.zip
Continuing in background, pid 1840.
Output will be written to 'wget-log'.
对于下载非常大的文件的时候,我们可以使用参数-b进行后台下载。 你可以使用以下命令来察看下载进度: $tail -f wget-log
wget --user-agent="Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16" http://www.minjieren.com/wordpress-3.1-zh_CN.zip
有些网站能通过根据判断代理名称不是浏览器而拒绝你的下载请求。不过你可以通过–user-agent参数伪装。 首先,保存一份下载链接文件,接着使用这个文件和参数-i下载: $cat > filelist.txt
url1
url2
url3
url4
$wget -i filelist.txt
$wget --mirror -p --convert-links -P ./LOCAL URL
$wget ftp-url
$wget --ftp-user=USERNAME --ftp-password=PASSWORD url
scp 跨机远程拷贝¶scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来。 Note 类似的工具有rsync;scp消耗资源少,不会提高多少系统负荷,在这一点上,rsync就远远不及它了。rsync比scp会快一点,但当小文件多的情况下,rsync会导致硬盘I/O非常高,而scp基本不影响系统正常使用。 命令格式:¶scp [参数] [原路径] [目标路径] 命令参数:¶
使用说明¶复制文件: $scp local_file remote_username@remote_ip:remote_folder
$scp local_file remote_username@remote_ip:remote_file
$scp local_file remote_ip:remote_folder
$scp local_file remote_ip:remote_file
指定了用户名,命令执行后需要输入用户密码;如果不指定用户名,命令执行后需要输入用户名和密码; 复制目录: $scp -r local_folder remote_username@remote_ip:remote_folder
$scp -r local_folder remote_ip:remote_folder
第1个指定了用户名,命令执行后需要输入用户密码; 第2个没有指定用户名,命令执行后需要输入用户名和密码; Note 从远程复制到本地的scp命令与上面的命令一样,只要将从本地复制到远程的命令后面2个参数互换顺序就行了。 使用示例¶$scp root@10.6.159.147:/opt/soft/demo.tar /opt/soft/
说明: 从10.6.159.147机器上的/opt/soft/的目录中下载demo.tar 文件到本地/opt/soft/目录中 $scp -r root@10.6.159.147:/opt/soft/test /opt/soft/
说明: 从10.6.159.147机器上的/opt/soft/中下载test目录到本地的/opt/soft/目录来。 $scp /opt/soft/demo.tar root@10.6.159.147:/opt/soft/scptest
说明: 复制本地opt/soft/目录下的文件demo.tar 到远程机器10.6.159.147的opt/soft/scptest目录 $scp -r /opt/soft/test root@10.6.159.147:/opt/soft/scptest
说明: 上传本地目录 /opt/soft/test到远程机器10.6.159.147上/opt/soft/scptest的目录中 crontab 定时任务¶通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令非常适合周期性的日志分析或数据备份等工作。 命令格式¶
命令参数¶
crontab的文件格式¶分 时 日 月 星期 要运行的命令
常用方法¶向cron进程提交一个crontab文件之前,首先要设置环境变量EDITOR。cron进程根据它来确定使用哪个编辑器编辑crontab文件。9 9 %的UNIX和LINUX用户都使用vi,如果你也是这样,那么你就编辑$HOME目录下的. profile文件,在其中加入这样一行: EDITOR=vi; export EDITOR
然后保存并退出。不妨创建一个名为<user> cron的文件,其中<user>是用户名,例如, davecron。在该文件中加入如下的内容。 # (put your own initials here)echo the date to the console every
# 15minutes between 6pm and 6am
0,15,30,45 18-06 * * * /bin/echo 'date' > /dev/console
保存并退出。注意前面5个域用空格分隔。 在上面的例子中,系统将每隔1 5分钟向控制台输出一次当前时间。如果系统崩溃或挂起,从最后所显示的时间就可以一眼看出系统是什么时间停止工作的。在有些系统中,用tty1来表示控制台,可以根据实际情况对上面的例子进行相应的修改。为了提交你刚刚创建的crontab文件,可以把这个新创建的文件作为cron命令的参数: $ crontab davecron
现在该文件已经提交给cron进程,它将每隔1 5分钟运行一次。同时,新创建文件的一个副本已经被放在/var/spool/cron目录中,文件名就是用户名(即dave)。 使用-l参数列出crontab文件: $ crontab -l
0,15,30,45 18-06 * * * /bin/echo `date` > dev/tty1
可以使用这种方法在$HOME目录中对crontab文件做一备份: $ crontab -l > $HOME/mycron
这样,一旦不小心误删了crontab文件,可以用上一节所讲述的方法迅速恢复。 如果希望添加、删除或编辑crontab文件中的条目,而EDITOR环境变量又设置为vi,那么就可以用vi来编辑crontab文件: $ crontab -e
可以像使用vi编辑其他任何文件那样修改crontab文件并退出。如果修改了某些条目或添加了新的条目,那么在保存该文件时, cron会对其进行必要的完整性检查。如果其中的某个域出现了超出允许范围的值,它会提示你。 我们在编辑crontab文件时,没准会加入新的条目。例如,加入下面的一条: # DT:delete core files,at 3.30am on 1,7,14,21,26,26 days of each month
30 3 1,7,14,21,26 * * /bin/find -name 'core' -exec rm {} \;
保存并退出。 Note 最好在crontab文件的每一个条目之上加入一条注释,这样就可以知道它的功能、运行时间,更为重要的是,知道这是哪位用户的定时作业。 $crontab -r
使用实例¶* * * * * myCommand
3,15 * * * * myCommand
3,15 8-11 * * * myCommand
3,15 8-11 */2 * * myCommand
3,15 8-11 * * 1 myCommand
30 21 * * * /etc/init.d/smb restart
45 4 1,10,22 * * /etc/init.d/smb restart
10 1 * * 6,0 /etc/init.d/smb restart
0,30 18-23 * * * /etc/init.d/smb restart
0 23 * * 6 /etc/init.d/smb restart
* */1 * * * /etc/init.d/smb restart
0 23-7 * * * /etc/init.d/smb restart
使用注意事项¶有时我们创建了一个crontab,但是这个任务却无法自动执行,而手动执行这个任务却没有问题,这种情况一般是由于在crontab文件中没有配置环境变量引起的。 在crontab文件中定义多个调度任务时,需要特别注环境变量的设置,因为我们手动执行某个任务时,是在当前shell环境下进行的,程序当然能找到环境变量,而系统自动执行任务调度时,是不会加载任何环境变量的,因此,就需要在crontab文件中指定任务运行所需的所有环境变量,这样,系统执行任务调度时就没有问题了。 不要假定cron知道所需要的特殊环境,它其实并不知道。所以你要保证在shelll脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。所以注意如下3点:
每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。 例如,可以在crontab文件中设置如下形式,忽略日志输出: 0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1
“/dev/null 2>&1”表示先将标准输出重定向到/dev/null,然后将标准错误重定向到标准输出,由于标准输出已经重定向到了/dev/null,因此标准错误也会重定向到/dev/null,这样日志输出问题就解决了。 系统级任务调度主要完成系统的一些维护操作,用户级任务调度主要完成用户自定义的一些任务,可以将用户级任务调度放到系统级任务调度来完成(不建议这么做),但是反过来却不行,root用户的任务调度操作可以通过”crontab –uroot –e”来设置,也可以将调度任务直接写入/etc/crontab文件,需要注意的是,如果要定义一个定时重启系统的任务,就必须将任务放到/etc/crontab文件,即使在root用户下创建一个定时重启系统的任务也是无效的。 新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。 当crontab失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错tail -f /var/log/cron。 千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。 在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+%Y%m%d’。 更新系统时间时区后需要重启cron,在ubuntu中服务名为cron: $service cron restart
ubuntu下启动、停止与重启cron: $sudo /etc/init.d/cron start
$sudo /etc/init.d/cron stop
$sudo /etc/init.d/cron restart
reStructuredText 简介¶reStructuredText是一种轻量级的文本标记语言,直译为:重构建的文本,为Python中Docutils项目的一部分。 其一般保存的文件以.rst为后缀。在必要的时候,.rst文件可以被转化成PDF或者HTML格式, 也可以有Sphinx转化为LaTex,man等格式,现在被广泛的用于程序的文档撰写。 参考链接: 标题(Title)¶来看看标题的实例: =====================
这是一个标题
=====================
---------------------
这也是一个标题
---------------------
#####################
这还是一个标题
#####################
reStructuredText可用于作为标题修饰的字符有很多很多: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
只要你想,上面的任意一个都可以用来作为标题的修饰符,当然,reStructuredText也是有推荐的,它推荐下面这些字符: = - ` : . ' " ~ ^ _ * + #
这些字符是上面一堆字符中稍微看起来不会那么奇怪的一部分,当然,个人建议不要那么花哨,尽量用这两个中的一个: = -
上面实例的写法也许有点复杂,.rst文件中,你还可以只给出下半部分的字符即可: 这和第一个标题一样
========================
对于相同的符号,有上标是一级标题,没有上标是二级标题。 标题最多分六级,可以自由组合使用。 全加上上标或者是全不加上标,使用不同的 6 个符号的标题依次排列,则会依次生成的标题为H1-H6。 =========
一级标题
=========
二级标题
=========
一级标题
^^^^^^^^
二级标题
---------
三级标题
>>>>>>>>>
四级标题
:::::::::
五级标题
'''''''''
六级标题
""""""""
Hint 作为修饰的字符长度要大于等于文字长度。另外,标题是能够嵌套的。 段落(Paragraphs)¶段落是reST文件的基本模块。段落一般隶属于某个章节中,是一块左对齐并且没有其他元素体标记的块。在.rst文件中,段落和 其他内容的分割是靠空行来完成,如果段落相较于其他的段落有缩进,reStructuredText会解析为引用段落,样式上有些不同。 这里是一段reStructuredText的内容,它可以很长很长。。。。最后,末尾留出空行表示是本段落的结束即可。
这里是另外一段reStructuredText的内容,这段内容和上一段之间,乃至后面的其他内容之间都要留出空行进行分割。
这个也是段落,当时由于缩进了,会变成引用段落。显示和直接的段落有点不同
列表(List)¶列表在HTML中被分为两种,一个是有序列表(Enumerated Lists),一种是无序列表(Bullet Lists),在reStructuredText中, 我们也能找到这两种列表,还有一种称为定义列表(Definition Lists),这和HTML中的DL一样,在.rst文件中可以支持嵌套列表。 无序列表 要求文本块是以下面这些字符开始,并且后面紧跟空格,而后跟列表项的内容,其中列表项比趋势左对齐并且有与列表对应的缩进。 * + - •
还是那句话,用最常用的几个字符就好,不用那么花哨。下面是示例: - 这里是列表的第一个列表项
- 这是第二个列表项
- 这是第三个列表项
- 这是缩进的第一个列表项
注意,这里的缩进要和当前列表项的缩进同步。
- 第一级的第四个列表项
- 列表项之间要用个空格来分割。
有序列表 在格式上和无序列表差不多,但是在使用的前缀修饰符上,使用的不是无序列表那种字符,而是可排序的字符,可以识别的有下面这些: arabic numerals: 1, 2, 3, ... (no upper limit).
uppercase alphabet characters: A, B, C, ..., Z.
lower-case alphabet characters: a, b, c, ..., z.
uppercase Roman numerals: I, II, III, IV, ..., MMMMCMXCIX (4999).
lowercase Roman numerals: i, ii, iii, iv, ..., mmmmcmxcix (4999).
如果你不想使用这些,在你标明第一个条目的序号字符后,第二个开始你还可以使用”#”号来让reStructuredText自动生成需要的序号(Docutils >= 0.3.8)。 1. 第一项
巴拉巴拉好多内容在这里。。。
#. 第二项
a. 第二项的第一小项
#. 第二项的第二小项
#. 第三项
定义列表 :每个定义列表项里面包含术语(term),分类器(classifiers,可选), 定义(definition)。术语是一行文字或者短语,分类器跟在术语后面, 用“ : ”(空格,冒号,空格)分隔。定义是相对于术语缩进后的一个块。定义中可以包含多个段落或者其他的内容元素。术语和定义之间可以没有空行, 但是在定义列表前后必须要有空行的存在。下面是示例: 术语1
术语1的定义
术语 2
术语2的定义,这是第一段
术语2的定义,第二段
术语 3 : 分类器
术语3的定义
术语 4 : 分类器1 : 分类器2
术语4的定义
Hint 在reStructuredText中,还有两种列表,一种是字段列表(Field Lists),一种是选项列表(Option Lists)。由于是rst的语法入门教程,这里不做深入介绍 块(Blocks)¶块在reStructuredText中的表现方式也有好几种,最常见的包括文本块、引用文本块、行块、引用块。 文本块(Literal Blocks)¶这种块的表达非常简单,就是在前面内容结束之后,用两个冒号” :: “(空格[Optional],冒号,冒号)来分割, 并在之后紧接着插入空行,而后放入块的内容,块内容要相对之前的内容有缩进。 这里是块之前的的内容。。。 ::
这里是块的内容。前面有缩进,空行,和::分隔符。
此处内容会被一直视为块内容
空行也不能阻断块内容。。
但是,当内容像这样,不再和块内容一样缩进时,块内容就自动的结束了。
这是块的最简单方式,一般我们编写的代码块就是用这种方式表现。 引用文本块(Quoted Literal Blocks)¶引用文本块是非缩进的连续文本块,其每一行以相同的非字母可打印7位ASCII字符开始。引用文本快由 空行结束。引用文本快会在处理过的文档中保存。 以下是所有有效缩进字符: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
Note 这与有效的章节标题装饰相同。 下面是引用文本块的例子: ! 这里是引用文本块的内容
! 这里是另一行
! 这是第三行
! 空行作为结束
行块(Line Blocks)¶行块对于地址块很有用。诗(诗歌、歌词)和无装饰列表等行结构有重要 意义。行块是一组由竖线(“|”)前缀开头的行。 每个竖线前缀表示一个新行,因此折行会被保留。初始缩进对于嵌套结构也很重要。支持行内标记。连续行被包装为 一个长的行,他们以一个空格代替竖线开始,左边必须对齐,但不需要与上面的文字的左边对齐。行块以空行结束。 这个例子展示了行块连续行: 这是一个行块的第一行,我需要打很多的字来填充
这一行,所以这些字可能没有什么意义,比如像这样的字,阿斯
蒂芬拉就是的房间辣豆腐机安检打发斯蒂芬,请你不要在意。。。
这是第二行,我真的没有时间打这么多字,所以我
比如像这样的字,阿斯蒂芬拉就是的房间辣豆腐机安检打发斯蒂芬,请你不要在意。。。
这是第二行,我真的没有时间打这么多字,所以我就复制粘贴了上一行的内容,所以这些
字可能没有什么意义,比如像这样的字,阿斯蒂芬拉就是的房间
辣豆腐机安检打发斯蒂芬,请你不要在意。。。
引用块(Block Quotes)¶一个以缩进与前面的文本关联的文本块,前面没有标记表示其为文被快或其他内容的,是引用块。 里面的所有标记会被连续处理(对于正文元素和行内标记) 这个例子展示了引用块:
样式(Style)¶reStructuredText中支持对文本进行样式控制,比如:粗体(Strong),斜体(Italic),等宽字体(Monospace),引用( interpreted text)。 .. Strong Emphasis
This is **Strong Text**. HTML tag is strong.粗体
.. Italic, Emphasis
This is *Emphasis* Text.这个HTML使用em, 斜体
.. Interpreted Text
This is `Interpreted Text`. 注意,这个HTML一般用<cite>表示
.. Inline Literals
This is ``Inline Literals``. HTML tag is <tt>. 等宽字体.
超链接(Hyperlink)¶介绍各类带有链接性质的超链接 参考链接: https://www.cnblogs.com/seayxu/p/5603876.html 外部超链接(External Hyperlink)¶引用/参考(reference),是简单的形式,只能是一个词语,引用的文字不能带有空格。 这篇文章来自我的Github,请参考 reference_。
.. _reference: https://www.google.com
这篇文章来自我的Github,请参考 reference。 引用/参考(reference),行内形式,引用的文字可以带有空格或者符号。 这篇文章来自我的Github,请参考 `Google <https://www.google.com>`_。
这篇文章来自我的Github,请参考 Google。 内部超链接|锚点(Internal Hyperlink)¶更多信息参考 引用文档_
这里是其他内容
.. _引用文档:
这是引用部分的内容
更多信息参考 引用文档 这里是其他内容 这是引用部分的内容 匿名超链接(Anonymous hyperlink)¶词组(短语)引用/参考(phrase reference),引用的文字可以带有空格或者符号,需要使用反引号引起来。 这篇文章参考的是:`Quick reStructuredText`__。
.. __: http://docutils.sourceforge.net/docs/user/rst/quickref.html
这篇文章来自我的Github,请参考 Quick reStructuredText。 间接超链接(Indirect Hyperlink)¶间接超链接是基于匿名链接的基础上的,就是将匿名链接地址换成了外部引用名。 SeayXu_ 是 `我的 GitHub 用户名`__。
.. _SeayXu: https://github.com/SeayXu/
__ SeayXu_
隐式超链接(Implicit Hyperlink)¶小节标题、脚注和引用参考会自动生成超链接地址,使用小节标题、脚注或引用参考名称作为超链接名称就可以生成隐式链接。 第一节 介绍
===========
其他内容...
隐式链接到 `第一节 介绍`_,即可生成超链接。
替换引用(Substitution Reference)¶替换引用就是用定义的指令替换对应的文字或图片,和内置指令(inline directives)类似。 这是 |logo| github的Logo,我的github用户名是:|name|。
.. |logo| image:: https://help.github.com/assets/images/site/favicon.ico
.. |name| replace:: Google
这是 Hint 我们会发现,两个处理连接的时候,都需要在链接文字前面要空格与前面进行分割,这个在英文当中比较好处理, 因为单个词之间有空格,而在中文中,字之间没有空格,如果加入空格,在显示时会有空格,影响观感,为此,如果在中文中使用,需要考虑好。 指令(Directives )¶指令是reStructuredText的扩展机制,一种添加支持新结构而不用添加新的语法(指令支持额外的本地语法)的方法。 如果reStructuredText的某种实现不能识别一个指令(如,指令处理器未安装 ),会生成一个3级(error)系统信息, 且整个指令块(包括指令本身)会被包含 为一个文本块。因为”::”是一个自然选择。 参考链接: http://docutils.sourceforge.net/docs/ref/rst/directives.html#code 主要的指令有以下几种: 警告指令¶警告类型有如下多种: attention, caution, danger, error, hint, important, note, tip, warning, admonition, title
警告被特别的标记为”topics”,可以呈现在任何原始正文元素呈现的位置。它们包含任意正文元素。通常, 警告被渲染为文档中的一个偏移块,有时是一个匹配警告类型的标题的概述或阴影。例如: Danger This is danger.
Beware killer rabbits!
Attention This is attention. Caution This is caution. Important This is important. 任何跟在指令指示器后的文本(在同一行和/或下一行缩进)都会被解释为一个指令块并被解析为普通的正文元素。 例如,下面的”note”警告指令包含一个段落和一个有两个列表项组成的无序列表: Note This is a note admonition. This is the second line of the first paragraph.
图片指令¶常用的两个图片指令: “image”和”figure” 下面是一个图片指令和所需选项的例子: .. image:: picture.jpeg
:height: 100px
:width: 200 px
:scale: 50 %
:alt: alternate text
:align: right
下列选项可以被识别:
代码¶支持的高亮语言: https://pygments.org/docs/lexers#lexers-for-various-shells 该链接的使用方法如下: .. highlight:: vim(Short names)
::
此处为需要高亮的文本内容(所有Filenames类型文件中的内容会被按语法高亮)
快速定义代码块¶使用简便的预定义高亮语法高亮缩进,默认不带语言说明的都使用highlight定义的语言高亮, 然后可以直接使用“::”两个冒号代替“code-block”指令快速定义其它代码块, 直到下一个highlight指令,才会改变语言: .. highlight:: sh
此指令后如下的“::”定义的块都会以sh语法进行高亮,直到遇到下一条highlight指令。
::
#此命令在主机执行
sudo apt install python
echo "helloworld,this is a script test!"
效果: #此命令在主机执行
sudo apt install python
echo "helloworld,this is a script test!"
code-block代码高亮¶shell 高亮测试¶高亮语法: .. code-block:: sh
:caption: test
:name: test333
:emphasize-lines: 2
:linenos:
#此命令在主机执行
sudo apt install python
echo "helloworld,this is a script test!"
效果: sh test¶
C高亮测试¶语法: .. code-block:: c
:caption: c test
:emphasize-lines: 4,5
:linenos:
#include <stdio.h>
int main()
{
printf("hello, world! This is a C program.\n");
for(int i=0;i<10;i++ ){
printf("output i=%d\n",i);
}
return 0;
}
效果: c test¶
verilog高亮测试¶语法: 使用verilog或v进行高亮 .. code-block:: v
:caption: verilog test
:emphasize-lines: 4,5
:linenos:
module key_filter
#(
parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(
input wire sys_clk , //系统时钟50Mhz
input wire sys_rst_n , //全局复位
input wire key_in , //按键输入信号
output reg key_flag //key_flag为1时表示消抖后检测到按键被按下
//key_flag为0时表示没有检测到按键被按下
);
效果: verilog test¶
literalinclude直接嵌入本地文件并高亮¶嵌入整个文件¶直接嵌入文件,包含标题、代码语言、高亮、带编号以及名称方便引用。 .. literalinclude:: ../../base_code/hello.c
:caption: ../../base_code/hello.c
:language: c
:emphasize-lines: 5,7-12
:linenos:
:name: hello.c
语法: .. literalinclude:: ../../base_code/hello_world.sh
:caption: ../../base_code/hello_world.sh
:language: sh
:linenos:
语法: .. literalinclude:: ../../base_code/Makefile
:caption: ../../base_code/Makefile
:language: makefile
:linenos:
嵌入文件的某部分¶通过lines指定嵌入文件的某些行。 语法: .. literalinclude:: ../../base_code/hello.c
:caption: ../../base_code/hello.c
:language: c
:linenos:
:lines: 1,3,5-8
rtd theme 配置¶rtd 主题由Read the Doc团队开发,主题美观大方。本小节将以此主题为例,说明主题如何自定义。 主题的配置文件在 [theme]
inherit = basic
stylesheet = css/theme.css
[options]
typekit_id = hiw1hhg
analytics_id =
sticky_navigation = False
logo_only =
collapse_navigation = False
display_version = True
navigation_depth = 4
prev_next_buttons_location = bottom
canonical_url =
基本选项含义:
导航栏选项:
更多说明,可见 官方文档 PDF输出:http://media.readthedocs.org/pdf/doclikecode/latest/doclikecode.pdf 其他例子¶该文本是 This is interpreted text. See the Python home page for info. This link is an alias to the link above. See the Python home page for info. This link is an alias to the link above. 关于计算机的一些问题¶这篇文章记录一些平时常见的关于计算机的问题 堆与栈的区别¶这篇文章讲解堆与栈的区别 程序的内存分配¶一个由C/C++编译的程序占用的内存分为以下几个部分:
例子程序¶这是一个前辈写的,非常详细: //main.cpp
int a = 0; //全局初始化区
char *p1; //全局未初始化区
main()
{
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456/0在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //123456/0放在常量区,编译器可能会将它与p3所指向的"123456" 优化成一个地方。
}
堆和栈的理论知识¶申请方式¶
申请后系统的响应¶
另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。 申请大小的限制¶
申请效率的比较¶
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。 堆和栈中的存储内容¶
存取效率的比较¶char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的,而bbbbbbbbbbb是在编译时就确定的,但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快,比如: #include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码: 10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,再根据edx读取字符,显然慢了。 小结¶堆和栈的区别可以用如下的比喻来看出:
Git简单教程¶这里简单讲解一下Git的使用方法 本地仓库如何上传到GitHub仓库¶方式一¶
Note 该方式无法保留之前的本地commit 方式二¶
Note 该方式可以保留本地之前的所有commit Git文件介绍¶介绍Git项目中的常见文件的作用 .gitattributes¶
VIM简单教程¶较好的Vim中文教程:https://vimjc.com/ 我的VIM配置文件¶_vimrc¶
创建网页笔记¶大家平时一定看过很多资料,查过很多资料,当时理解了,但是过后又忘了,等到需要用的时候又要重新去搜索,这浪费了很多时间,解决这个问题最好的办法就是有一个专属自己的笔记本,我自己也记过很多笔记,比如写个word、txt之类的,但是笔记多了之后就容易乱,而且有时候会觉得这些文档工具的排版不是很美观,这时候如果有一个专业排版的云端网页笔记本,那所有的问题就解决了,本文档就是教你如何创建属于自己的云端网页笔记。 所需工具¶创建网页笔记所需的工具有Sphinx、GitHub、Readthedocs。下面对这些工具做个简单的介绍:
为了帮助理解,打个比方,Sphinx就像是一个编译器,他可以将我们按照一定的reStructuredText语法编写的文档代码翻译成优美的可读的文档,就像LaTeX可以将代码翻译成PDF文档一样。我们写好的文档代码可以放在本地磁盘,也可以放在云端仓库,GitHub就是这个云端仓库。Readthedocs就是托管我们的文档,让它以网页的形式展示给我们。 Sphinx安装¶几篇教程:
TBD Git安装与GitHub的使用¶GitHub的几篇教程:
TBD Readthedocs的使用¶TBD Windows开发环境快速搭建¶Important 只针对Windows10系统,其他Windows系统可能有安装依赖问题
My Java Learning¶Big Data11¶Machine L¶暖通空调(HVAC)¶本文可以作为HVAC(Heating, ventilation, and air conditioning)家用空调系统的故障排查指南 暖气炉的简要工作原理¶Furnace 是三种气流协同工作的结果,他们互相配合但决不互相泄露。 ![]() 在暖气炉中工作的气流
暖气炉启动流程¶![]() 暖气炉简易启动流程图 暖气炉的启动和电脑的启动一样,有个复杂的过程。这个过程不同品牌的机器略有差异,但基本类似。启动中如果控制板检测到某个零件损坏或者未达到工作需要的参数,机器会立刻停机,我们也就可以大致确定与这个零件有关联的零部件可能需要维护或者更换。这就是检修的基本方法。
暖气炉检修步骤¶
从这一部分开始,我们将按照机器的启动程序,逐步逐个介绍每个零件的工作原理和检测方法。 1. 温控器¶温控器就是thermostat(以下简称thst)。温控器实际上就是一个多功能多线/位电源开关。一般常见的型号有四个接线端,分别叫R,W,Y,G。这四个接线端和暖炉控制板上的接线端一摸一样,所以安装时只要将暖炉的四个接线端的信号线连接到温控器同样名称的接线端,温控器就可以控制暖炉的启动和停机工作。暖炉启动后,一切控制权交由暖炉控制板完成。其实温控器就是完成电源开和关的操作。 这四个接线端的功能是:R-24/36伏电源,W-暖炉,Y-冷气机,G-暖炉室内风扇。当环境温度低于或者高于温控器的设定温度时,温控器就会将R 分别和W 或者Y 接通,使暖炉或者冷气机的控制板获得控制权。当温控制器的风扇开关选择"auto"时,R将和G端开路,风扇的工作由控制板控制。当温控器的风扇开关选择"on"时,R会连接G端,使室内风扇持续运转,无论暖炉或者冷气机是否处于工作状态。 基于上述原理,检查时,先拔下温控器面板,用电笔寻找/核对有电的线,即是R 线。将R分别和W/Y/G连接,如果对应设备能运转,说明对应设备无故障,温控器可能已损坏和需要更换电池。如对应设备不能运转,说明需要进一步检查对应设备。 ![]() 暖炉和兼容电脑构造很类似,都是一个个件靠锣丝拧紧拼起来的。所以一般主体不坏就不换机。暖炉的核心主体是热交换器,换这个件需要很多费用,而且整个机器都得拆开,这个动作不亚于工厂里装一台新机。所以这时如果年限高点一般都是换炉划算。 2. Rollout Switch (火焰外燃开关)¶Rollout switch是暖炉防止过热的保护设备之一。火焰正确的燃烧位置是热交换器内。当火焰蔓延到热交换器外时,暖炉的内部结构物和各种零件的温度会迅速升高,很容易烧毁暖炉的零件及相关的信号线路,甚至导致房屋失火。当火焰外燃开关的温度传感器达到厂家设计温度时(这个控制点不可调),开关会断开而中断信号回路,使控制板及时发现火焰外燃,并切断暖炉的工作电源和煤气供应。所以rolloutswitch 实际上就是一个具有温度属性的开关,温度控制点是350F。和high limit switch的区别在于温度控制点。 外燃开关的正常状态是闭合的,损坏时为开路。可使用万用表鸥拇挡量侧开关的两个接线端的电阻值以判断开关的连通状态。 当火焰外燃开关失效时,室内风机和燃烧风机会持续运行,暖气出风口和暖炉排气管都会吹冷风,直到暖炉重新启动或者外燃开关闭合。 ![]() 3. LimitSwitch (过热开关)¶故名思意,过热开关就是防止系统温度太高而被烧坏的保护装置。和火焰外燃开关一样,过热开关也是一种温度开关,区别在于安装位置和温度工作点不同。过热开关通常安装在热交换器外,且室内风机迫使室内空气循环的热风管道内。所以他的主要任务则是监测热风管道内的工作温度。一旦这个温度太高,超过了热交换器的承受能力,过热开关将断开信号回路,控制板获得信号后立刻切断煤气阀门和燃烧风机的电源,防止热交换器被烧坏,同时强制室内风机运转,迅速带走热量,降低热交换器的温度。 过热开关的正常状态是闭合的,损坏时为开路。可使用万用表鸥拇挡量侧开关的两个接线端的电阻值以判断开关的连通状态。 当过热开关失效时时,室内风机会持续运行,但出风口吹出来的是冷风。如果室内风机失效,则暖炉外壳温度很高,但出风口却没有热风吃出来。 ![]() Windows开发笔记¶不用DLL实现键盘钩子¶g_hHook=SetWindowsHookEx(WH_JOURNALRECORD,KeyboardProc,GetModuleHandle(NULL),0); 常用的API¶LowLevelKeyboardProc callback function KBDLLHOOKSTRUCT structure (winuser.h) ShellExecuteA function (shellapi.h) WM_XBUTTONDOWN message SetWindowsHookExA function (winuser.h) SetWindowsHookExA function (winuser.h) KBDLLHOOKSTRUCT structure (winuser.h) LowLevelMouseProc function MSLLHOOKSTRUCT structure (winuser.h) LoadImageA function (winuser.h) MAKEINTRESOURCEA macro (winuser.h) GetModuleHandleA function (libloaderapi.h) MouseProc callback function WindowProc callback function SendInput function (winuser.h) MapVirtualKeyA function (winuser.h) WM_KEYDOWN message About Keyboard Input PostMessageA function (winuser.h) keybd_event function (winuser.h) CreateCompatibleBitmap function (wingdi.h) WM_SYSKEYDOWN message Sleep function (synchapi.h) RegisterHotKey function (winuser.h) CreateIconIndirect function (winuser.h) CreateWindowA macro (winuser.h) WM_HOTKEY message C++语法笔记¶
Read the Docs
v: latest
Free document hosting provided by Read the Docs. |