• 使用命令行修改Linux系统的时区

    系统时区目录 系统支持时区的配置文件存放在 /usr/share/zoneinfo/ 目录下,可以进入到该目录下查看和搜索目标时区的相关配置文件。

    时区配置文件 Linux系统的当前时区配置文件存放在 /etc/localtime , 可以将时区配置文件拷贝到该位置下,也可以建立一个软连接指向系统时区目录中的配置文件。

    操作示例 以将系统的时区改为中国时间为例,以下操作先将旧的时区配置文件删掉,然后建立新的时区配置文件的符号链接。

    rm /etc/localtime
    ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    

    完成以上操作后,可以执行 date 命令查看修改效果。

  • Linux常用命令行指令 - netstat

    常见的选项有:
    -a (all)显示所有选项,netstat默认不显示LISTEN相关
    -t (tcp)仅显示tcp相关选项
    -u (udp)仅显示udp相关选项
    -n 拒绝显示别名,能显示数字的全部转化成数字。(重要)
    -l 仅列出有在 Listen (监听) 的服务状态
    -p 显示建立相关链接的程序名(macOS中表示协议 -p protocol)
    -r 显示路由信息,路由表
    -e 显示扩展信息,例如uid等
    -s 按各个协议进行统计 (重要)
    -c 每隔一个固定时间,执行该netstat命令。

  • Linux常用命令行指令 - tcpdump

    tcpdump常用于网络抓包,能够将抓取的包保存下来,这样就能进一步深入分析。抓包保存的文件可以使用tcpdump进行查看,也可以借助第三方软件(如wireshark)进行辅助分析。

    1. 抓取指定网络设备上的包

    抓取网卡eth0上的包

    tcpdump -i eth0
    

    2. 限制抓包的数量

    只抓取5个包

    tcpdump -c 5 -i eth0
    

    3. 将抓取的包以ASCII的方式打印出来

    tcpdump -A -i eth0
    

    4. 将抓取的包以十六进制的方式打印出来

    tcpdump -XX -i eth0
    

    5. 对抓取到的包上打出更方便阅读的时间戳

    增加 -t 参数能够将抓取到的包中的时间以方便阅读的形式打印出来,使用 -tttt 参数能够将包中的时间戳以更详细的方式打印出来。

    tcpdump -t -i eth0
    tcpdump -tttt -i eth0
    

    6. 将抓取的包写入到文件中

    tcpdump -w netdump.pcap -i eth0
    

    7. 读取抓到的包

    tcpdump -r netdump.pcap
    

    8. 在抓到的包中显示ip地址

    增加 -n 参数不会解析主机名,增加 -nn 参数不会解析主机名和端口名

    tcpdump -n -i eth0
    tcpdump -nn -i eth0
    

    9. 以绝对值显示包的ISN号

    tcpdump -S -i eth0
    

    10. 对抓取到的包显示更详细的信息

    参数 -v 是verbose的缩写,以下命令表示对抓取到的包显示更详细的信息。

    tcpdump -v -i eth0
    tcpdump -vv -i eth0
    tcpdump -vvv -i eth0
    

    11. 对抓到的包进行协议类型过滤

    支持的协议类型有:fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp, udp
    以下命令只会抓取网卡eth0上的arp包

    tcpdump -i eth0 arp
    

    12. 在抓包时对包进行大小过滤

    下面的命令会分别抓取大于1024字节和小于1024字节的包

    tcpdump -i eth0 greater 1024
    tcpdump -i eth0 less 1024
    

    13. 抓取指定端口上的包

    tcpdump -i eth0 port 22
    

    14. 抓取发往指定目的和端口上包

    可以使用 andor 对过滤条件进行组合以实现精确的抓包。

    tcpdump -w net_dump.pcap -i eth0 dst 10.181.140.216 and port 22
    

    常用tcpdump命令示例

    tcpdump –i any 'port 8888'
    tcpdump –i any 'tcp port 8888'
    tcpdump –i any 'tcp src port 8888'
    tcpdump –i any 'tcp src port 8888 and udp dst port 9999'
    tcpdump -i any 'src host 127.0.0.1 and tcp src port 12345' -XX -nn -vv
    
  • Linux常用命令行指令 - nc

    nc 命令是 netcat 的缩写,能够使用TCP或UDP协议读写网络连接中的数据,是一个方便可靠的调试工具。

  • Linux常用命令行指令 - lsof

    lsof是list open files的简称,用于列出系统中所有打开的文件。由于在linux系统下,所有 对象都是文件,所以这个指令十分有用。

    下面就给出了几种常见的用法,需要注意的是有些指令需要root权限执行。

    1. 查看打开指定文件的进程

    lsof /var/syslog.log
    

    2. 查看指定目录下打开的文件

    lsof +D /home/
    

    3. 查看以指定进程名所有打开的文件

    使用 -c 命令能够查看指定进程名使用的文件,允许在一个命令行指令中使用多个 -c 参数。

    lsof -c procname
    

    4. 查看使用指定挂载点的进程

    在停止挂载某个目录时,系统会告诉我们“设备资源繁忙”,所以我们需要找出使用挂载点的程序,终止这些进程,解除目录的占用状态。

    lsof /home
    


    lsof +D /home/
    

    5. 查看指定用户打开的文件

    lsof -u username
    

    另外还可以进行反向过滤,在输出中不显示指定用户的文件,语法如下。

    lsof -u ^username
    

    6. 查看指定进程打开的文件

    lsof -p pid
    

    7. 终止属于某个用户的所有进程

    kill `lsof -t -u username`
    

    相似的,可以使用 -t 参数打印使用某个文件的进程id。

    lsof -t /var/log
    

    8. 让结果同时满足多个选项

    默认情况下,多个参数是以或(or)进行操作的,可以使用 -a 选项让结果同时满足多个参数。

    lsof -a -u username -c procname
    

    9. 让命令重复执行

    可以使用 -r 参数让命令重复执行。以下命令会每隔5s执行一次,每次的执行结果会用 “====” 分割开。

    lsof -u username -c procname -a -r5
    

    10. 列出所有的网络连接

    lsof -i
    

    让结果中的ip地址和端口号显示数字而不是英文别名

    lsof -i -Pn
    

    显示所有的 AF_UNIX socket

    lsof -U
    

    11. 列出指定进程使用的网络连接

    lsof -i -a -p pid
    

    12. 查看指定端口上的监听

    lsof -i :portid
    

    13. 列出所有tcp和udp连接

    lsof -i tcp; lsof -i udp
    

    14. 列出所有的网络文件系统

    网络文件系统(network file system)

    lsof -N -u username
    
  • 重载、覆盖和隐藏的区别

    重载(overload) :就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
    多个重载函数在调用的时候根据函数的参数来区别不同的函数。
    关键点:函数名相同,参数表不同

    覆盖(override) :是指在派生类中重新对基类中的虚函数重新实现,即函数名和参数都一样,只是函数的实现体不一样。
    关键词:派生类中,虚函数,函数名和参数表完全相同

    隐藏(hide) :派生类中的函数把基类中相同名字的函数屏蔽掉了。
    隐藏一词可以这么理解:在调用一个类的成员函数的时候,编译器会沿着类的继承链逐级的向上查找函数的定义,如果找到了那么就停止查找了,所以如果一个派生类和一个基类都有同一个同名(暂且不论参数是否相同)的函数,而编译器最终选择了在派生类中的函数,那么我们就说这个派生类的成员函数"隐藏"了基类的成员函数,也就是说它阻止了编译器继续向上查找函数的定义.

    关于这三种情况的示例代码如下

    #include <iostream.h>
    class Base
    {
    public:
      virtual void f(float x)
      {
        cout << "Base::f(float) " << x << endl;
      }
    
      void g(float x)
      {
        cout << "Base::g(float) " << x << endl;
      }
    
      void h(float x)
      {
        cout << "Base::h(float) " << x << endl;
      }
    };
    
    class Derived : public Base
    {
    public:
      virtual void f(float x)
      {
        cout << "Derived::f(float) " << x << endl;
      }
    
      void g(int x)
      {
        cout << "Derived::g(int) " << x << endl;
      }
    
      void h(float x)
      {
        cout << "Derived::h(float) " << x << endl;
      }
    };
    

    从以上代码能够看出:
    (1)函数Derived::f(float)覆盖了Base::f(float)。
    (2)函数Derived::g(int)隐藏了Base::g(float),而不是重载。
    (3)函数Derived::h(float)隐藏了Base::h(float),而不是覆盖。

    考虑代码在运行时的结果:

    void main(void)
    {
      Derived  d;
      Base *pb = &d;
      Derived *pd = &d;
    
      // Good : behavior depends solely on type of the object
      pb->f(3.14f); // Derived::f(float) 3.14
      pd->f(3.14f); // Derived::f(float) 3.14
    
      // Bad : behavior depends on type of the pointer
      pb->g(3.14f); // Base::g(float) 3.14
      pd->g(3.14f); // Derived::g(int) 3        (surprise!)
    
      // Bad : behavior depends on type of the pointer
      pb->h(3.14f); // Base::h(float) 3.14      (surprise!)
      pd->h(3.14f); // Derived::h(float) 3.14
    }
    

    在第一种调用中,函数的行为取决于指针所指向的对象。在第二第三种调用中,函数的行为取决于指针的类型。所以说,隐藏破坏了面向对象编程中多态这一特性,会使得开发人员产生混乱。

    函数接口设计注意要点
    在设计基类的函数接口时,不要出现既是虚函数,又对该虚函数进行了重载的情况。这样会对派生类的多态函数实现造成不便。
    示例代码如下

    class Base
    {
      virtual foo();
      virtual foo(int n);
    }
    
    class Derived : public Base
    {
      virtual foo();
    }
    

    从以上代码能够看出:

    1. Derived::foo()Base::foo() 构成了多态关系
    2. Derived::foo() 隐藏了 Base::foo(int)

    所以,如果派生类希望实现 foo() 函数的多态,也就必须实现 foo(int) 的多态,否则就会出现隐藏。
    如果在现有代码中已经发生了上述 Base 的情况,在不改变原有代码的情况下,可以使用在派生类中使用这样的语法 using Base::foo; ,这会将基类中所有的名为 foo 的函数引入到派生类中来。