• Linux常用命令行指令 - top

    linux的top命令能够动态显示当前系统的运行状态。它能够显示操作系统的汇总信息和当前系统上的正在运行的进程列表。

    统计信息说明

    (可以通过配置文件修改通计信息区的显示格式,下文所描述的都是在默认配置下的显示内容)

    第1行

    • 当前系统时间
    • 当前系统的启动时长
    • 当前登录的用户数量
    • 当前系统的平均负载(分别是1min,5min,10min的平均负载)

    这一行信息也可以通过 uptimew 指令获得

    第2行

    • 总进程数
    • 正在运行的进程数
    • 休眠的进程数
    • 停止的进程数
    • 僵尸进程数

    第3行

    • us 用户空间占用CPU百分比
    • sy 内核空间占用CPU百分比
    • ni 用户进程空间内改变过优先级的进程占用CPU百分比
    • id 空闲CPU百分比
    • wa 等待输入输出的CPU时间百分比
    • hi CPU服务于硬件中断所耗费的时间总额
    • si CPU服务软中断所耗费的时间总额
    • st Steal time 虚拟机被hypervisor偷去的CPU时间(如果当前处于一个hypervisor下的vm,实际上hypervisor也是要消耗一部分CPU处理时间的)

    第4行

    • 物理内存总量
    • 使用的物理内存总量
    • 空闲内存总量
    • 用作内核缓存的内存量

    第5行

    • 交换区总量
    • 使用的交换区总量
    • 空间交换区总量
    • 缓冲交换区总量

    进程信息

    在top命令中按f按可以查看显示的列信息,按对应字母来开启/关闭列,大写字母表示开启,小写字母表示关闭。带*号的是默认列。

    A: PID = (Process Id) 进程Id;
    E: USER = (User Name) 进程所有者的用户名;
    H: PR = (Priority) 优先级
    I: NI = (Nice value) nice值。负值表示高优先级,正值表示低优先级
    O: VIRT = (Virtual Image (kb)) 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
    Q: RES = (Resident size (kb)) 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
    T: SHR = (Shared Mem size (kb)) 共享内存大小,单位kb
    W: S = (Process Status) 进程状态。D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程
    K: %CPU = (CPU usage) 上次更新到现在的CPU时间占用百分比
    N: %MEM = (Memory usage (RES)) 进程使用的物理内存百分比
    M: TIME+ = (CPU Time, hundredths) 进程使用的CPU时间总计,单位1/100秒
    b: PPID = (Parent Process Pid) 父进程Id
    c: RUSER = (Real user name)
    d: UID = (User Id) 进程所有者的用户id
    f: GROUP = (Group Name) 进程所有者的组名
    g: TTY = (Controlling Tty) 启动进程的终端名。不是从终端启动的进程则显示为 ?
    j: P = (Last used cpu (SMP)) 最后使用的CPU,仅在多CPU环境下有意义
    p: SWAP = (Swapped size (kb)) 进程使用的虚拟内存中,被换出的大小,单位kb
    l: TIME = (CPU Time) 进程使用的CPU时间总计,单位秒
    r: CODE = (Code size (kb)) 可执行代码占用的物理内存大小,单位kb
    s: DATA = (Data+Stack size (kb)) 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb
    u: nFLT = (Page Fault count) 页面错误次数
    v: nDRT = (Dirty Pages count) 最后一次写入到现在,被修改过的页面数
    y: WCHAN = (Sleeping in Function) 若该进程在睡眠,则显示睡眠中的系统函数名
    z: Flags = (Task Flags <sched.h>) 任务标志,参考 sched.h
    X: COMMAND = (Command name/line) 命令名/命令行

    参考资料

  • 云服务器安全相关配置

    我所租用的云服务器操作系统为CentOS Linux,在使用云服务器的过程中为了保证服务器的安全,进行了一些简单的配置,这样能够增加服务器被破解的难度。

  • C风格和C++风格的文件操作库函数总结

    由于C++是兼容C的,所以使用C++进行文件操作时,会发现有两套库函数可以使用,它们分别是C风格的和C++风格的。

    C风格的文件操作函数

    打开文件,关闭文件

    #include <stdio.h>
    FILE* fopen(const char* path, const char* mode);
    int fclose(FILE* fp);
    

    读取文件,写入文件

    #include <stdio.h>
    size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
    size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);
    

    关于fread中两个表示大小的参数,在这个 stackoverflow 问题中得到了比较好的解答。

    改变文件指示器的位置

    #include <stdio.h>
    int fseek(FILE* stream, long offset, int whence);
    long ftell(FILE* stream);
    void rewind(FILE* stream);
    

    C++风格的文件操作函数

    C++将文件操作函数封装为 fstream 操作类,一个文件实际上就会对应一个 fstream 对象,一下函数都是 fstream 的成员函数。
    文件打开和关闭

    void open(const char* filename, ios_base::openmode mode = ios_base::in|ios_base::out);
    void open(const std::string& filename, ios_base::openmode mode = ios_base::in|ios_base::out);
    void close();
    

    对于文件的读写可以才采用流运算符重载的方法完成。

    friend fstream& operator << (fstream& ofs, const CRecord& objRecord);
    friend fstream& operator >> (fstream& ifs, CRecord& objRecord);
    

    题外话

    在liunx下,可以使用wc命令查看文件中的相关信息。wc命令会打印出该文件的行数、单词数、字符数。

  • 字节序与union类型

    字节序

    字节序是指在数据传输时,高位字节存储在内存中的较高位地址还是较低位地址。
    字节序分为大端字节序和小端字节序,两种字节序不能混用。
    大端字节序 :高位字节保存在较低位地址的内存中
    小端字节序 :高位字节保存在较高位地址的内存中

    int n = 0x12345678 为例,大端字节序内存中的存储的顺序为 0x12 0x34 0x56 0x78 ,小端字节序内存中的存储顺序为 0x78 0x56 0x34 0x12 。很明显可以看出大端字节序更符合人类的阅读习惯。

    常见的大端系统CPU:IBM z/Atchitecture
    常见的小端系统CPU:intel x86

    网络字节序使用的大端字节序,常用网络协议如IPv4、IPv6、TCP和UDP协议都是使用大端字节序完成数据传输的。

    查看当前系统的字节序

    通过 lscpu 命令,能得到cpu的大端和小端信息。

    lscpu | grep -i endian
    

    通过常用shell命令,在大端系统中会输出0,在小端系统中会输出1。

    echo -n I | od -to2 | head -n1 | cut -f2 -d" " | cut -c6
    

    借助python进行判断。

    python -c "import sys; print(sys.byteorder)"
    # or
    python -c "import sys;sys.exit(0 if sys.byteorder=='big' else 1)"
    

    借助linux的ELF进行判断,查看第6个字节,小端系统中为1,大端系统中为2。

    xxd -c 1 -l 6 /bin/bash
    # or
    hexdump -n 6 -C /bin/bash
    

    union类型

    可以使用union类型验证字节序,以下示例代码在不同的字节序下会有不同的输出。

    #include <stdio.h>
    #include <inttypes.h>
    
    typedef union un {
        int32_t x;
        char ch[4];
    }un;
    
    int main() {
        un u;
        u.ch[0] = 1;
        u.ch[1] = 2;
        u.ch[2] = 3;
        u.ch[3] = 4;
        printf("u.x=0x%x\n", u.x);
        return 0;
    }
    
  • 在Python日志中输出文件名和函数名

    Python内置了日志模块,在默认情况下输出的日志是不带文件名和函数名的,这样在排查问题时,遇到相似的日志就变得容易混淆,可以通过设置将输出的日志中带有文件名和函数名。参考了stackoverflow的回答,详细代码如下。

    import logging
    log = logging.getLogger('root')
    LOG_FORMAT = "%(filename)s:%(lineno)s %(funcName)s() %(message)s"
    logging.basicConfig(format=LOG_FORMAT)
    log.setLevel(logging.DEBUG)
    

    参考资料
    stackoverflow

  • Linux常用命令行指令 - xargs

    基础用法

    xargs 指令默认情况下从 stdin 中读取信息,按照空格分或换行区分开,并且执行输入的命令(默认的命令是 /bin/echo )。命令可以通过 xargs 的参数指定执行一次或多次,命令的执行参数为自身初始参数追加上由 stdin 读到的内容,命令在执行时会忽略空行。

    xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command (default is /bin/echo) one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.

    在命令行输入 xargs 命令,输入 “a b c d” 后按回车,再按 ctrl+d 完成本次输入,则 xargs 的默认 echo 命令会将接收到的字符串打印出来,效果如下所示。

    # xargs
    a b c d
    a b c d
    

    xargs 单独使用时功能比较单一,但是它与其他指令一起使用十分强大。

    xargsfind 组合使用

    常见的使用方法是使用 find 指令找到指定的文件,组合以 xargs 指令实现对指定文件的操作。

    find . -name "demo_" | xargs file -i
    

    由于 xargs 是使用空格作为各个参数的分隔符,如果遇到的文件名中含有空格,则并不能按照预期处理。这时,可以使用 find 指令的 -print0 将含有空格的文件名转化为字符串,再结合 xargs-0 参数就能完成文件名中含有空格的处理,改进后的命令如下。

    find . -name "demo_" -print0 | xargs -0 file -i
    

    xargsgrep 组合使用

    常用命令如下,能够实现对指定规则文件的搜索匹配。

    find . -name "*.log" | xargs grep error
    

    使用 -n 参数让 xargs 的命令重复执行

    如果想用 find 指令完成多个匹配规则的搜索,则可以使用 -n 参数将 xargs 的内容分割成多个。
    下面的命令会执行3次 find 命令, xargs 会将接收的到的内容按照单词数为“1”分割,分3次传送给 find 指令。

    echo "*.c" "*.cpp" "*.h" | xargs -n 1 find . -name
    

    使用 -t 参数让 xargs 打印将要执行的命令

    xargs 将指令的命令打印出来主要是方便查看命令执行情况,也方便在出现错误时进行调试。

    find . -name *.log | xargs -t rm -f
    

    使用 -p 参数让 xargs 在执行命令前询问用户

    增加 -p 参数后, xargs 在每次执行命令前会将指令打印出来并询问用户,只有用户输入 “y” 时才会真正执行该条命令。

    echo "*.c" "*.cpp" "*.h" | xargs -n 1 -p find . -name
    

    使用 -I 参数让 xargs 进行参数替换

    xargs 默认会将读取到的内容追加在指令命令后面作为参数,使用 -I 参数能够控制命令参数的组合方式。
    以下命令会将当前目录中的可执行文件移动到bin文件夹下。

    find . -executable -type f -print0 | xargs -0 -I {} mv {} ./bin