http://learn.akae.cn/media/index.html
http://lxr.linux.no/#linux+v2.6.34/Documentation/networking/
#strace,lstrace,truss
http://hi.baidu.com/jordie/item/c6d6a71ce0488cfc756a842e?
http://os.51cto.com/art/201207/347414.htm
zjw@ubuntu:~/2014/0106$ gdb a.out GNU gdb (GDB) 7.1-ubuntu Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/zjw/2014/0106/a.out...done. (gdb) set follow-fork-mode child (gdb) b b_foo Function "b_foo" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (b_foo) pending. (gdb) r Starting program: /home/zjw/2014/0106/a.out a_foo:17349 this is a parent process!, ret pid=17349 [New process 17349] a_foo:0 this is a child process!, getpid=17349 process 17349 is executing new program: /home/zjw/2014/0106/b.out [Switching to process 17349] Breakpoint 1, b_foo (argc=4, argv=0xbffff7f4) at b.c:11 11 for(i=0; i<argc; i++){ (gdb) shell cat a.c b.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <errno.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> void a_foo(pid_t pid) { printf("%s:%u\n", __FUNCTION__, pid); if(pid == 0){ printf("%s, getpid=%u\n", "this is a child process!", getpid()); execl("./b.out", "b.out", "-o", "xxx", "pid, ppid, pgrp, session, tpgid, comm", NULL); }else { printf("%s, ret pid=%u\n", "this is a parent process!", pid); int stat_val; waitpid(pid, &stat_val, 0); if(WIFEXITED(stat_val)){ printf("chlild exited with code %d\n", WEXITSTATUS(stat_val)); } else { printf("unknown\n"); } } } int main(int argc, char **argv) { pid_t pid; pid = fork(); a_foo(pid); return 0; } #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <errno.h> #include <unistd.h> void b_foo(int argc, char **argv) { int i; for(i=0; i<argc; i++){ printf("argv[%d]=%s\n", i, argv[i]); sleep(1); } } int main(int argc, char **argv) { int c = argc; char **v = argv; b_foo(c, v); return 0; } (gdb) shell cat makefile all: gcc -g a.c -o a.out gcc -g b.c -o b.out clean: rm -rf *.out (gdb)
vim
http://www.cnblogs.com/wally/p/3452288.html
gdb
http://blog.csdn.net/water_cow/article/details/7214054
epoll
http://blog.csdn.net/piaojun_pj/article/details/6103709
http://m.blog.csdn.net/blog/hjxhjh/9374837
pcap
http://blog.csdn.net/huaxi1902/article/details/8792084
http://www.cnblogs.com/huyc/archive/2011/10/19/2217134.html
sk_buff
http://simohayha.iteye.com/blog/556168
gtest
http://www.habadog.com/2011/09/06/gtest-newhand-forself/
http://blog.csdn.net/butterflydog/article/details/7005045
http://www.cnblogs.com/coderzh/archive/2009/04/11/1433744.html
http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
http://hi.baidu.com/xiaoduo170/item/acf686f55346a7de6325d25c
// epoll 使用 //创建 服务端 socket fd server_sockfd=socket(PF_INET,SOCK_STREAM,0) //bind 端口号 bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr) //设置listen 队列长度 listen(server_sockfd,5); // 创建epoll 句柄epd epoll_fd=epoll_create(MAX_EVENTS) // 将服务段socket fd 加入到epd 监听事件集中 epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_sockfd,&ev) while(1) // 获取发生的事件个数 nfds=epoll_wait(epoll_fd,events,MAX_EVENTS,-1) // 阻塞直到有事件发生 for(i<nfds){ // 客户段第一次连接 if(events[i].data.fd==server_sockfd) //获取 客户端 socket fd clinet_sockfd = accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size) //将客户端 socket fd 注册到 epd 监听事件集中 poll_ctl(epoll_fd,EPOLL_CTL_ADD,client_sockfd,&ev) else recv(client_sockfd,buf,BUFFER_SIZE,0) send(client_sockfd,"....",WriteSize,0); }
=============================
经常使用这些工具,有那么些功能却不常用,也不知道。
1. gdb
a. .gdbinit
gdb运行时会首先加载 ~/.gdbinit文件
例如:我在debug时,每次都需要进行handle SIGBUS noprint pass来处理SIGBUS信号,这种情况就可以把它写入 .gdbinit文件。
在.gdbinit里也可以定义函
eg: 在.gdbinit里定义print_regs
def print_regs
i r eax ebx ecx edx
end
(gdb) print_regs
eax 0xbffff4a4 -1073744732
ebx 0x28bff4 2670580
ecx 0x902c5562 -1876142750
edx 0x1 1
b. 在GDB中,可以使用命令up或down在栈中移动!上下移动栈,查询变量和内存的值。这个有什么好处呢?
看看如下的例子就知道了
test0(a){
int m = GetNumber();
test1(b);
}
test1(b){
test3(c);
}
执行到test3(c)的时候,如果你想看看test0中的变量m的值是多少,怎么办?这时就可以使用up了,up到test0的栈时就可以直接print m的值了。很方便!
c. 设置临时断点 tbreak
d. 如果watch变量不好用,可以watch它的地址
e. return 和jump命令
return <expr> :return 从函数退出,跳过剩下的语句。
jump :跳过或重新执行当前函数中的语句。
f. shared library
可以显示哪些DLL已经载入,并且为尚未载入调试信息的DLL载入调试信息
g. 按下Ctrl + C,只是暂停程序,程序还可以继续运行。
h. 注意设置条件断点有可能会影响执行速度。
如果需要在某条执行特别频繁的语句上设置条件断点,则比较好的方法是在代码中直接插入源代码做判断,这样速度更快。
2. strace
在进行以下高度时可以考虑使用strace:
a. 查明哪些文件被打开了
b. 在OS全程中未捕获的错误或中断。用strace查找返回的错误值,并再次核对源代码 是否处理了这些值
c. 调试性能问题,看OS调用的频率
d. 查看内存分配、释放、映射的情况。
==============================
strace是Linux中一个调试和跟踪工具。
它可以接管被跟踪进程执行的系统调用和收到的信号。然后把每一个执行的系统调用的名字,参数和返回值打印出来。可以通过strace找到问题出现在user层还是kernel层。
strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。
参数详解::
-p pid 跟踪指定的进程pid. //(后台Server开发,经常使用)
-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.
-s size 设置显示的buf,如果是0,表示完整显示。
-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
-s strsize
指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username
以username的UID和GID执行被跟踪的命令.
注意strace 存在的风险:
1、strace 可能会使 semop错误退出,并且errno=EINTR,为了防止strace让程序推出,需要在程序中作判断,if(errno==EINTR) continue;
2、strace 会让一些进程成为T状态,这时进程停止运行,需要给进程发一个信号,才可以继续运行kill -CONT pid
3、strace 会让一些进程成为Z状态。
进程中状态的含义:
S,sleep等待,休眠
R,就绪
Z,zombie僵死,进程的最后状态,完成使命,给父进程留下一个记录(退出码,一些时间统计信息)
T,由父进程跟踪,通过信号停止的进程
X,由等待内存资源被封锁。
I,除进程0以外的所有进程的起始态,属于过渡态,虽存在,但没有被封锁,但也不能运行。
++++++++++++++++++++++++++++++++++
strace使用举例:
strace -t whoami #跟踪whoami可执行程序,每行输出结果前打印执行的时间
strace -p 17151 -p 17152 -p 17153 #同时跟踪进程17151、17152、17153
strace -f -e trace=read,write -p 17151 -o log #跟踪进程17151及子进程中read和write系统调用,输出到log文件
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。gcc编译时加上-g参数,可以使可执行程序加上gdb调试信息。
(1)info
简写:i,列出gdb子命令的信息,如info break,info variables,info stack等。
(2)list [file:]function==================================
kill | 终止正在调试的程序的执行 | 通常这会在要执行的代码行已经超过了您想要调试的代码时使用。执行kill会重置断点,并从头再次运行这个程序 |
break | 在指定的行或函数处设置断点 | break 93 if i=8- 当变量 i 等于 8 时,在第 93 行停止程序执行 |
info thread | 显示当前正在运行的线程 | ? |
thread apply threadno command | 对一个线程运行 gdb 命令 | thread apply 3 where- 对线程 3 运行where命令 |
Thread threadno | 选择一个线程作为当前线程 |
gdb -pid 9510. 查看每个线程运行到了什么地方
(gdb) thread apply 1 where |
+++++++++++++++++++++++++++++++++++++++++
这是“你应该知道的Unix和Linux命令”系列的第三篇,在这篇文章中,我会介绍lsof这个工具,如果说netcat 是进行网络诊断的瑞士军刀,那么lsof就是Unix调试的瑞士军刀。
Lsof是遵从Unix哲学的典范,它只做一件事情,并且做的相当完美——它可以列出某个进程打开的所有文件信息。打开的文件可能是普通的文件,目录,NFS文件,块文件,字符文件,共享库,常规管道,明明管道,符号链接,Socket流,网络Socket,UNIX域Socket,以及其它更多。因为Unix系统中几乎所有东西都是文件,你可以想象lsof该有多有用。
你可以看看这系列文章第一篇对pipe viewer的介绍,如果你对这篇文章感兴趣,那你应该订阅我的RSS Feed(译者注:也别忘了订阅黑客志 :)。
如何使用lsof?
这篇文章中我会尽力列举我能想到的所有lsof的用法,让我们先从最简单的开始(或许你已经知道了),然后逐渐增加复杂度:
列出所有打开的文件
# lsof
不带任何参数运行lsof会列出所有进程打开的所有文件。
找出谁在使用某个文件
# lsof /path/to/file
只需要执行文件的路径,lsof就会列出所有使用这个文件的进程,你也可以列出多个文件,lsof会列出所有使用这些文件的进程。
你也可以一次制定多个文件:
# lsof /path/to/file1 /path/to/file2
递归查找某个目录中所有打开的文件
# lsof +D /usr/lib
加上+D参数,lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢:
# lsof | grep '/usr/lib'
之所以慢是因为+D首先查找所有的文件,然后一次性输出。
列出某个用户打开的所有文件
# lsof -u pkrumins
-u选项限定只列出所有被用户pkrumins打开的文件,你可以通过逗号指定多个用户:
# lsof -u rms,root
这条命令会列出所有rms和root用户打开的文件。
你也可以像下面这样使用多个-u做同样的事情:
# lsof -u rms -u root
查找某个程序打开的所有文件
# lsof -c apache
-c选项限定只列出以apache开头的进程打开的文件:
所以你可以不用像下面这样写:
# lsof | grep foo
而使用下面这个更简短的版本:
# lsof -c foo
事实上,你可以只制定进程名称的开头:
# lsof -c apa
这会列出所有以apa开头的进程打开的文件
你同样可以制定多个-c参数:
# lsof -c apache -c python
这会列出所有由apache和python打开的文件
列出所有由某个用户或某个进程打开的文件
# lsof -u pkrumins -c apache
你也可以组合使用多个选项,这些选项默认进行或关联,也就是说上面的命令会输入由pkrumins用户或是apache进程打开的文件。
列出所有由一个用户与某个进程打开的文件
# lsof -a -u pkrumins -c bash
-a参数可以将多个选项的组合条件由或变为与,上面的命令会显示所有由pkrumins用户以及bash进程打开的文件。
列出除root用户外的所有用户打开的文件
# lsof -u ^root
注意root前面的^符号,它执行取反操作,因此lsof会列出所有root用户之外的用户打开的文件。
列出所有由某个PID对应的进程打开的文件
# lsof -p 1
-p选项让你可以使用进程id来过滤输出。
记住你也可以用都好来分离多个pid。
# lsof -p 450,980,333
列出所有进程打开的文件除了某个pid的
# lsof -p ^1
同前面的用户一样,你也可以对-p选项使用^来进行取反。
列出所有网络连接
# lsof -i
lsof的-i选项可以列出所有打开了网络套接字(TCP和UDP)的进程。
列出所有TCP网络连接
# lsof -i tcp
也可以为-i选项加上参数,比如tcp,tcp选项会强制lsof只列出打开TCP sockets的进程。
列出所有UDP网络连接
# lsof -i udp
同样udp让lsof只列出使用UDP socket的进程。
找到使用某个端口的进程
# lsof -i :25
:25和-i选项组合可以让lsof列出占用TCP或UDP的25端口的进程。
你也可以使用/etc/services中制定的端口名称来代替端口号,比如:
# lsof -i :smtp
找到使用某个udp端口号的进程
# lsof -i udp:53
同样的,也可以找到使用某个tcp端口的进程:
# lsof -i tcp:80
找到某个用户的所有网络连接
# lsof -a -u hacker -i
使用-a将-u和-i选项组合可以让lsof列出某个用户的所有网络行为。
列出所有NFS(网络文件系统)文件
# lsof -N
这个参数很好记,-N就对应NFS。
列出所有UNIX域Socket文件
# lsof -U
这个选项也很好记,-U就对应UNIX。
列出所有对应某个组id的进程
# lsof -g 1234
进程组用来来逻辑上对进程进行分组,这个例子查找所有PGID为1234的进程打开的文件。
列出所有与某个描述符关联的文件
# lsof -d 2
这个命令会列出所有以描述符2打开的文件。
你也可以为描述符指定一个范围:
# lsof -d 0-2
这会列出所有描述符为0,1,2的文件。
-d选项还支持其它很多特殊值,下面的命令列出所有内存映射文件:
# lsof -d mem
txt则列出所有加载在内存中并正在执行的进程:
# lsof -d txt
输出使用某些资源的进程pid
# lsof -t -i
-t选项输出进程的PID,你可以将它和-i选项组合输出使用某个端口的进程的PID,下面的命令将会杀掉所有使用网络的进程:
# kill -9 `lsof -t -i`
循环列出文件
# lsof -r 1
-r选项让lsof可以循环列出文件直到被中断,参数1的意思是每秒钟重复打印一次,这个选项最好同某个范围比较小的查询组合使用,比如用来监测网络活动:
# lsof -r 1 -u john -i -a
如何安装lsof?
许多Unix系统都内置了lsof,如果你的系统没有安装,你可以从这里直接下载源代码。
BSD系统有一个类似的工具可以做同样的事情,叫做fstat。
你可以通过man lsof来了解关于lsof的完整文档,或者通过lsof -h查看。
开始体验lsof的乐趣吧!
------------
本文翻译自"A Unix Utility You Should Know About: lsof",作者:Peteris Krumins,照片:Hallvard E
++++++++++++++++++++++++++++++++++++++++
再分享一些可能你不知道的shell用法和脚本,简单&强大!
在阅读以下部分前,强烈建议读者打开一个shell实验,这些都不是shell教科书里的大路货哦:)
1、!$<!$是一个特殊的环境变量,它代表了上一个命令的最后一个字符串。如:你可能会这样:
$mkdir mydir |
可以改成:
$mkdir mydir |
2、sudo !!以root的身份执行上一条命令 。
场景举例:比如Ubuntu里用apt-get安装软件包的时候是需要root身份的,我们经常会忘记在apt-get前加sudo。每次不得不加上sudo再重新键入这行命令,这时可以很方便的用sudo !!完事。
【陈皓:酷壳博主(@左耳朵耗子)注:在shell下,有时候你会输入很长的命令,你可以使用!xxx来重复最近的一次命令,比如,你以前输入过,vi /where/the/file/is, 下次你可以使用 !vi 重得上次最近一次的vi命令。】
3、cd –回到上一次的目录。
场景举例:当前目录为/home/a,用cd ../b切换到/home/b。这时可以通过反复执行cd –命令在/home/a和/home/b之间来回方便的切换。
(陈皓注:cd ~ 是回到自己的Home目录,cd ~user,是进入某个用户的Home目录)
4、‘ALT+.’ or ‘<ESC> .’热建alt+. 或 esc+. 可以把上次命令行的参数给重复出来。
5、^old^new替换前一条命令里的部分字符串。
场景:echo "wanderful",其实是想输出echo "wonderful"。只需要^a^o就行了,对很长的命令的错误拼写有很大的帮助。(陈皓注:也可以使用 !!:gs/old/new)
6、du -s * | sort -n | tail
列出当前目录里最大的10个文件。
7、:w !sudo tee %
在vi中保存一个只有root可以写的文件
8、date -d@1234567890
时间截转时间
9、> file.txt
创建一个空文件,比touch短。
10、mtr coolshell.cn
mtr命令比traceroute要好。
在命令行前加空格,该命令不会进入history里。
11、echo “ls -l” | at midnight
在某个时间运行某个命令。
12、curl -u user:pass -d status=”Tweeting from the shell” http://twitter.com/statuses/update.xml
命令行的方式更新twitter。
13、curl -u username –silent “https://mail.google.com/mail/feed/atom” | perl -ne ‘print “\t” if /<name>/; print “$2\n” if /<(title|name)>(.*)<\/\1>/;’
检查你的gmail未读邮件
14、ps aux | sort -nk +4 | tail
列出头十个最耗内存的进程
15、man ascii
显示ascii码表。
场景:忘记ascii码表的时候还需要google么?尤其在天朝网络如此“顺畅”的情况下,就更麻烦在GWF多应用一次规则了,直接用本地的man ascii吧。
16、ctrl-x e
快速启动你的默认编辑器(由变量$EDITOR设置)。
17、netstat –tlnp
列出本机进程监听的端口号。(陈皓注:netstat -anop 可以显示侦听在这个端口号的进程)
18、tail -f /path/to/file.log | sed '/^Finished: SUCCESS$/ q'
当file.log里出现Finished: SUCCESS时候就退出tail,这个命令用于实时监控并过滤log是否出现了某条记录。
19、ssh user@server bash < /path/to/local/script.sh
在远程机器上运行一段脚本。这条命令最大的好处就是不用把脚本拷到远程机器上。
20、ssh user@host cat /path/to/remotefile |http://images.51cto.com/files/uploadimg/20121123/1109370.png -gravity NorthWest -background transparent -extent 720×200 output.png
改一下图片的大小尺寸
21、lsof –i
实时查看本机网络服务的活动状态。
22、vim scp://username@host//path/to/somefile
vim一个远程文件
23、python -m SimpleHTTPServer
一句话实现一个HTTP服务,把当前目录设为HTTP服务目录,可以通过http://localhost:8000访问 这也许是这个星球上最简单的HTTP服务器的实现了。
24、history | awk '{CMD[$2]++;count++;} END { for (a in CMD )print CMD[a] " " CMD[a]/count*100 "% " a }' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10
(陈皓注:有点复杂了,history|awk ‘{print $2}’|awk ‘BEGIN {FS=”|”} {print $1}’|sort|uniq -c|sort -rn|head -10)
这行脚本能输出你最常用的十条命令,由此甚至可以洞察你是一个什么类型的程序员。
25、tr -c “[:digit:]” ” ” < /dev/urandom | dd cbs=$COLUMNS conv=unblock | GREP_COLOR=”1;32″ grep –color “[^ ]“
想看看Marix的屏幕效果吗?(不是很像,但也很Cool!)
看不懂行代码?没关系,系统的学习一下*nix shell脚本吧,力荐《Linux命令行与Shell脚本编程大全》。
最后还是那句Shell的至理名言:(陈皓注:下面的那个马克杯很不错啊,404null.com挺有意思的)。
++++++++++++++++++++++++++++++++++++++++
ssh配置
主机A:10.0.5.199
主机B:10.0.5.198
需要配置主机A无密码登录主机A,主机B
先确保所有主机的防火墙处于关闭状态。
在主机A上执行如下:
1. $cd ~/.ssh
2. $ssh-keygen -t rsa --------------------然后一直按回车键,就会按照默认的选项将生成的密钥保存在.ssh/id_rsa文件中。
3. $cp id_rsa.pub authorized_keys
这步完成后,正常情况下就可以无密码登录本机了,即ssh localhost,无需输入密码。
4. $scp authorized_keys [email protected]:/home/summer/.ssh ------把刚刚产生的authorized_keys文件拷一份到主机B上.
5. $chmod 600 authorized_keys
进入主机B的.ssh目录,改变authorized_keys文件的许可权限。
(4和5可以合成一步,执行: $ssh-copy-id -i [email protected] )
正常情况下上面几步执行完成后,从主机A所在机器向主机A、主机B所在机器发起ssh连接,只有在第一次登录时需要输入密码,以后则不需要。
可能遇到的问题:
1.进行ssh登录时,出现:”Agent admitted failure to sign using the key“ .
执行: $ssh-add
强行将私钥 加进来。
2.如果无任何错误提示,可以输密码登录,但就是不能无密码登录,在被连接的主机上(如A向B发起ssh连接,则在B上)执行以下几步:
$chmod o-w ~/
$chmod 700 ~/.ssh
$chmod 600 ~/.ssh/authorized_keys
3.如果执行了第2步,还是不能无密码登录,再试试下面几个
$ps -Af | grep agent
检查ssh代理是否开启,如果有开启的话,kill掉该代理,然后执行下面,重新打开一个ssh代理,如果没有开启,直接执行下面:
$ssh-agent
还是不行的话,执行下面,重启一下ssh服务
$sudo service sshd restart
4. 执行ssh-add时提示“Could not open a connection to your authenticationh agent”而失败
执行: ssh-agent bash