巧用lsof查找消失的空间

Publish: January 18, 2019 Category: Shell No Comments

    今天遇到个奇怪的事情,使用df -h命令的时候,发现var满了,190G全满了。

[root@xxxxxx]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              16G  635M   15G   5% /
tmpfs                  16G     0   16G   0% /dev/shm
/dev/sda7             570G  154G  387G  29% /data1
/dev/sda6              16G  173M   15G   2% /tmp
/dev/sda5              20G  6.1G   13G  33% /usr
/dev/sda3             197G   15G  173G   8% /var

然后使用 du -sh 去查var下面哪个目录,发现var只用了15G,找不到使用者,如下

[root@xxxxxx]# du -sh /var/*
4.0K    /var/account
141M    /var/cache
93M     /var/cfengine
4.0K    /var/crash
4.0K    /var/cvs
104K    /var/db
8.0K    /var/empty
4.0K    /var/games
95M     /var/lib
4.0K    /var/local
16K     /var/lock
15G     /var/log
20K     /var/lost+found

[root@xxxxxx]# du -sh /var/
15G     /var/

奇怪了吧,最后刚上查了下,发现可能有文件已经删除,但进程还在使用,就使用如下命令

[root@xxxxxx]# lsof |grep deleted
php         525     root    5uW     REG                8,3          0    9365330 /var/tmp/sqlite_hrggjoghXxuVeNw (deleted)
php         525     root    8u      REG                8,3         20    9365331 /var/tmp/sqlite_hrggjoghXxuVeNw-journal (deleted)
crond      2008     root    3u      REG                8,3          5    3767505 /var/run/crond.pid (deleted)
python    30172     root   10u      REG                8,6       4096         21 /tmp/ffi6zRKh3 (deleted)
python    30175     root   10u      REG                8,6       4096         22 /tmp/ffie68Mj3 (deleted)

最后杀掉进程即可~。




使用openssl做md5,sha,hmac加密

Publish: January 17, 2019 Category: C/C++ No Comments

依赖openssl, 所以确保安装了openssl-devel库

ctcrypt.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/conf.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>

/*
 * @param in_str        需要md5的源字符串
 * @param in_str_len    源字符串的长度
 * @param out_str       保存md5后的字符串buf
 * @param out_str_size  out_str的空间长度
 *
 * @return 0 成功  1 失败
 */
int ct_md5(char *in_str, size_t in_str_len, char *out_str, size_t out_str_size)
{
    MD5_CTX         hash_ctx;
    unsigned char   hash_ret[16];
    int             i;
    if (*in_str == '\0' || in_str_len == 0) {
        return 1;
    }
    // initialize a hash context
    if (MD5_Init(&hash_ctx) == 0) {
        return 1;
    }
    // update the input string to the hash context (you can update
    // more string to the hash context)
    if (MD5_Update(&hash_ctx, in_str, in_str_len) == 0) {
        return 1;
    }
    
    // compute the hash result
    if (MD5_Final(hash_ret, &hash_ctx) == 0) {
        return 1;
    }
    char *pout = out_str;
    int pout_len = 0;
    for (i=0; i<32; i++) {
        if (i%2 == 0) {
            pout_len += snprintf(pout+pout_len, out_str_size - pout_len, "%x", (hash_ret[i/2] >> 4) & 0xf);
        } else {
            pout_len += snprintf(pout+pout_len, out_str_size - pout_len, "%x", (hash_ret[i/2]) & 0xf);
        }
    }
    return 0;
}


/*
 * sha1加密
 * @param in_str        需要sha1的源字符串
 * @param in_str_len    源字符串的长度
 * @param out_str       保存sha1后的字符串buf
 * @param out_str_size  out_str的空间长度
 *
 * @return 0 成功  1 失败
 */
int ct_sha1(char *in_str, size_t in_str_len, char *out_str, size_t out_str_size)
{
    SHA_CTX         hash_ctx;
    unsigned char   hash_ret[20];
    int             i;
    // initialize a hash context
    if (SHA1_Init(&hash_ctx) == 0) {
        return 1;
    }
    if (SHA1_Update(&hash_ctx, in_str, in_str_len) == 0) {
        return 1;
    }
    if (SHA1_Final(hash_ret, &hash_ctx) == 0) {
        return 1;
    }
    
    char *pout = out_str;
    int pout_len = 0;
    for (i=0; i<40; i++) {
        if (i%2 == 0) {
            pout_len += snprintf(pout+pout_len, out_str_size - pout_len, "%x", (hash_ret[i/2] >> 4) & 0xf);
        } else {
            pout_len += snprintf(pout+pout_len, out_str_size - pout_len, "%x", (hash_ret[i/2]) & 0xf);
        }
    }
    return 0;
}


/*
 * hash_hmac加密
 * @param algo          使用hash的算法: 
 *                          md2, md4, md5, sha, sha1, dss, dss1, ecdsa, sha224,
 *                          sha256, sha384, sha512, ripemd160, whirlpool
 * @param data          被hash的数据
 * @param data_len      被hash的数据的长度
 * @param key           Shared secret key used for generating the HMAC variant of the message digest.
 * @param key_len       key的长度
 * @param out_data      保存hash后的字符串buf
 * @param out_data_size out_data的空间长度
 *
 * @return 0 成功  1 失败
 */
int ct_hash_hmac(char *algo, char *data, size_t data_len, char *key, size_t key_len, char *out_data, size_t out_data_size)
{
    HMAC_CTX        *hash_ctx;
    unsigned char   hash_ret[20];
    unsigned int    hash_ret_len = 20;
    int             i;
    const EVP_MD    *evp_md;
    
    if (algo == NULL) {
        evp_md = EVP_md_null();
    } else if (strcasecmp(algo, "md2") == 0) {
        evp_md = EVP_md2();
    } else if (strcasecmp(algo, "md4") == 0) {
        evp_md = EVP_md4();
    } else if (strcasecmp(algo, "md5") == 0) {
        evp_md = EVP_md5();
    } else if (strcasecmp(algo, "sha") == 0) {
        evp_md = EVP_sha();
    } else if (strcasecmp(algo, "sha1") == 0) {
        evp_md = EVP_sha1();
    } else if (strcasecmp(algo, "dss") == 0) {
        evp_md = EVP_dss();
    } else if (strcasecmp(algo, "dss1") == 0) {
        evp_md = EVP_dss1();
    } else if (strcasecmp(algo, "ecdsa") == 0) {
        evp_md = EVP_ecdsa();
    } else if (strcasecmp(algo, "sha224") == 0) {
        evp_md = EVP_sha224();
    } else if (strcasecmp(algo, "sha256") == 0) {
        evp_md = EVP_sha256();
    } else if (strcasecmp(algo, "sha384") == 0) {
        evp_md = EVP_sha384();
    } else if (strcasecmp(algo, "sha512") == 0) {
        evp_md = EVP_sha512();
    } else if (strcasecmp(algo, "ripemd160") == 0) {
        evp_md = EVP_ripemd160();
    } else if (strcasecmp(algo, "whirlpool") == 0) {
        evp_md = EVP_whirlpool();
    }
    
    hash_ctx = HMAC_CTX_new();
    HMAC_CTX_init(hash_ctx);
    
    if (HMAC_Init_ex(hash_ctx, key, key_len, evp_md, NULL) == 0) {
        return 1;
    }
    
    if (HMAC_Update(hash_ctx, (unsigned char *)data, data_len) == 0) {
        return 1;
    }
    
    if (HMAC_Final(hash_ctx, hash_ret, &hash_ret_len) == 0) {
        return 1;
    }
    
    HMAC_CTX_cleanup(hash_ctx);
    HMAC_CTX_free(hash_ctx);
    
    char *pout = out_data;
    int pout_len = 0;
    for (i=0; i<hash_ret_len; i++) {
        pout_len += snprintf(pout+pout_len, out_data_size - pout_len, "%02x", (unsigned int)hash_ret[i]);
    }
    return 0;
}


ctcrypt.h:

#ifndef _CTCRYPT_H_
#define _CTCRYPT_H_
/*
 * md5加密
 * @param in_str        需要md5的源字符串
 * @param in_str_len    源字符串的长度
 * @param out_str       保存md5后的字符串buf
 * @param out_str_size  out_str的空间长度
 *
 * @return 0 成功  1 失败
 */
int ct_md5(char *in_str, size_t in_str_len, char *out_str, size_t out_str_size);


/*
 * sha1加密
 * @param in_str        需要sha1的源字符串
 * @param in_str_len    源字符串的长度
 * @param out_str       保存sha1后的字符串buf
 * @param out_str_size  out_str的空间长度
 *
 * @return 0 成功  1 失败
 */
int ct_sha1(char *in_str, size_t in_str_len, char *out_str, size_t out_str_size);


/*
 * hash_hmac加密
 * @param algo          使用hash的算法: 
 *                          md2, md4, md5, sha, sha1, dss, dss1, ecdsa, sha224,
 *                          sha256, sha384, sha512, ripemd160, whirlpool
 * @param data          被hash的数据
 * @param data_len      被hash的数据的长度
 * @param key           Shared secret key used for generating the HMAC variant of the message digest.
 * @param key_len       key的长度
 * @param out_data      保存hash后的字符串buf
 * @param out_data_size out_data的空间长度
 *
 * @return 0 成功  1 失败
 */
int ct_hash_hmac(char *algo, char *data, size_t data_len, char *key, size_t key_len, char *out_data, size_t out_data_size);

#endif


sample.c:

/*
 * 使用方法:
 *  # gcc -g -o sample sample.c -I/usr/include/ -L/usr/lib64/ -lcrypto
 *  # ./sample 'hello, world'
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ctcrypt.h"
int main(int argc, char **argv)
{
    char out_string[1024] = {0};
    int ret = 0;
    
    ret = ct_md5(argv[1], strlen(argv[1]), out_string, sizeof(out_string));
    printf("md5     ret[%d]:%s\n", ret, out_string);
    
    memset(out_string, 0, sizeof(out_string));
    ret = ct_sha1(argv[1], strlen(argv[1]), out_string, sizeof(out_string));
    printf("sha1    ret[%d]:%s\n", ret, out_string);
    
    memset(out_string, 0, sizeof(out_string));
    char key[] = "012345678";
    ret = ct_hash_hmac("sha1", argv[1], strlen(argv[1]), key, strlen(key), out_string, sizeof(out_string));
    printf("hmac    ret[%d]:%s\n", ret, out_string);
    
    return 0;
    
}


SSR 一键安装

Publish: July 24, 2018 Category: 默认分类 No Comments

使用91yun自动安装脚本: https://github.com/91yun/shadowsocks_install


完全重写了之前SSR的一键安装包。

  • 直接使用git clone的方式安装作者的源码,免去我要不断跟进更新的麻烦

  • 直接使用ssr stop之类的命令方便管理

  • 直接使用作者mujson的方式进行用户管理,无论单用户还是多用户都很方便

  • 通过命令添加/删除用户,centos会自动开防火墙端口

  • 可以通过命令直接更新/uninstall程序

  • 有问题欢迎随时反馈


SSR的几个默认设置:

  • ssr代码安装在/home/ssr/下。

  • 默认的加密方式是:chacha20

  • 默认的协议是:auth_sha1_v4_compatible

  • 默认的混淆是:tls1.2_ticket_auth_compatible


SSR的一键安装命令:

wget -N --no-check-certificate https://raw.githubusercontent.com/91yun/shadowsocks_install/master/ssr-install.sh && bash ssr-install.sh


安装完后会直接提示新增用户:

1. 输入密码,默认91yun.org:

2. 输入端口:

3. 按任意键开始安装:

4. 最后复制ssr链接就可以方便的导入ssr客户端了:



SSR一键包的几个命令:

  • 添加用户:ssr adduser

  • 删除用户:ssr deluser

  • 启动SSR:ssr start

  • 停止SSR:ssr stop

  • 重启SSR:ssr restart

  • 卸载SSR:ssr uninstall

  • 更新SSR:ssr update


如果你想自己修改用户和的加密,混淆和协议的话:

修改vi /home/ssr/mudb.json文件

[
{
"d": 0,
"enable": 1,
"method": "chacha20",
"obfs": "tls1.2_ticket_auth_compatible",
"passwd": "91yun.org",
"port": 9191,
"protocol": "auth_sha1_v4_compatible",
"transfer_enable": 9007199254740992,
"u": 0,
"user": "9191"
}
]


几个参数的说明:

  • method:加密方法

  • passwd:ssr密码

  • port:ssr端口

  • protocol:协议

  • obfs:混淆

  • transfer_enable:流量

大家可以自己视情况修改。



如果新的有问题,大家依然可以使用旧的安装方式:

wget -N --no-check-certificate https://raw.githubusercontent.com/91yun/shadowsocks_install/master/shadowsocksR.sh && bash shadowsocksR.sh
  • 默认加密为: chacha20

  • 默认协议为: auth_sha1_v4

  • 默认混淆为: tls1.2_ticket_auth


使用命令:

  • 启动: /etc/init.d/shadowsocks start

  • 停止: /etc/init.d/shadowsocks stop

  • 重启: /etc/init.d/shadowsocks restart

  • 状态: /etc/init.d/shadowsocks status

  • 配置文件路径: /etc/shadowsocks.json

  • 日志文件路径: /var/log/shadowsocks.log

  • 安装路径: /usr/local/shadowsocks/shadowsoks


解决僵死进程defunct方式

Publish: September 14, 2017 Category: C/C++ No Comments

这里有以下几种方式解决僵死进程:

忽略子进程退出信号

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <strings.h>

void sig_catch( int sig, void (*f) () )
{
    struct sigaction sa;
    sa.sa_handler = f;
    sa.sa_flags   = 0;
    sigemptyset(&sa.sa_mask);
    sigaction(sig, &sa, (struct sigaction *) 0);
}

sig_catch(SIGCHLD, SIG_IGN);


2. 父进程wait子进程退出信号

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <strings.h>

#define wait_crashed(w) ((w) & 127)
#define wait_exitcode(w) ((w) >> 8)

int wait_pid(int *wstat, int pid)
{
    int r;
    do
        r = waitpid(pid, wstat, 0);
    while ((r == -1) && (errno == EINTR));
    return r;
}


int main(int argc, char **argv) 
{
    pid_t   pid;

    switch (pid = fork()) {
        case -1:
            printf("fork error\n");
            return 1;
        case 0:
            printf("child[%d]: exit\n");
            _exit(31);
    }

    int wstat;
    int exitcode;

    int pid_w = wait_pid(&wstat, pid);
    if (pid_w != pid) {
        printf("waitpid fail. pid_w[%lld] pid[%lld]\n", pid_w, pid);
        return 1;
    }
    
    if (wait_crashed(wstat)) {
        printf("waitpid crashed \n");
        return 1;
    }
    
    exitcode = wait_exitcode(wstat);
    printf("child[%lld] exit code[%d]\n", pid, exitcode);

    return 0;
}


3. Catch子进程信号,并在处理函数内wait (注意这个函数里不可以做syslog调用,在大量并发时会程序异常)

// 此函数内不可调用syslog
void sigchld_exit()
{
    int exitcode;
    int wstat, pid;
    while ((pid = waitpid(-1, &wstat, WNOHANG)) > 0) {
        //log_info("child[%ld] exit[%d]", pid, wstat);
        if (wait_crashed(wstat)) {
            //log_error("child[%ld] crashed[%d]", pid, wstat);
            return;
        }   
        exitcode = wait_exitcode(wstat);
        //log_info("child[%ld] exitcode[%d]", pid, exitcode);
    }   
}

{
    sig_catch(SIGCHLD, sigchld_exit);
}

inetd,xinetd守护进程

Publish: August 31, 2017 Category: Shell,C/C++ No Comments

    inetd, xinetd 为每一个服务都建立侦听socket,当inetd,xinetd收到连接时,它首先确定该socket协议和端口所对应的服务程序,然后fork子进程来启动exec该服务程序,并把连接的通信socket描述符作为标准输入、标准输出和标准错误输出描述符传递给子进程。

    这种方式,不但不需要为每个服务启动独立的服务程序,而且在设计这些服务程序时,还可以避免考虑复杂的socket编程,所需的仅仅是简单的字符串分析。比如telnet、ftp等,都是通过 inetd, xinetd 守护进程来实现的。


xinetd:

  1. 设置文件: /etc/services

# 在文件尾添加一行:
sj    20227/tcp

此文件记录了 xinetd 守护的每个服务的基本信息,包括名称、端口号和协议类型。此例添加了服务 sj 占用TCP协议的20227端口。


  2. 设置文件: /etc/xinetd.d/sj

service sj
{
    socket_type = stream
    protocol    = tcp 
    wait        = no
    user        = root
    only_from   = 198.72.5.0 localhost  
    banner      = /usr/home/grayson/deny_banner
    server      = /usr/home/grayson/sj_server
}

这是一个常见的服务配置文件。我们逐行看一下:

  • 第一行指定这是一个服务并给服务取一个名称。

  • socket_type 描述连接如何工作,常常是 stream(用于 TCP 连接)或 dgram(用于 UDP 服务)。

  • wait 控制 xinetd 是每次处理一个连接 (wait=yes),还是每次处理多个连接 (wait=no)。

  • user 指定守护进程应该作为哪个用户运行。这个用户常常是根用户(超级用户),但是某些服务最好或必须作为服务的创建者运行。

  • only_from 指定哪些系统可以对这个服务发出请求。在这里,只允许 198.72.5 子网上的系统和本地主机使用 sj 服务。最右边的 0 作为通配符;允许 IP 地址前缀为 198.72.5 的任何系统请求服务。可以使用多种表示法指定系统;详情参见 xinetd.conf 手册页。(输入 man 5 xinetd.conf。)如果允许所有就去掉这行!

  • 如果禁止访问,就把 /usr/local/etc/deny_banner 文件的内容发送给客户机。

  • 最后,server 指定允许访问时运行的可执行程序。


  3. 重启服务:

service xinetd restart

    

  4. 服务: sj_server

#include <stdio.h>
int main()
{
    char buf[1024] = {0};
    printf("Welcome!\n");
    fflush(stdout);
    while (1) {
        fgets(buf, sizeof(buf), stdin);     // 读取请求
        printf("Input: %s", buf);           // 返回应答
        fflush(stdout);
        if (strncmp(buf, "exit", 4) == 0)
            break;
    }
    return 0;
}

  5. 编译

# gcc -g -o sj_server sj_server.c