c++ killUserProc 杀死某个用户包含某些关键字的进程

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <pwd.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <signal.h>

using namespace std;

class Process {
public:
    int _pid;
    int _uid;
    string _name;
    string _cmdline;

    Process(const int& pid, const int& uid, const string& name, const string& cmdline): 
    _pid(pid), _uid(uid), _name(name), _cmdline(cmdline) {};
};

uid_t getUserUid(string userName) {
    //获得指定用户名的ID
    uid_t uid = -1;
    struct passwd *pwd = getpwnam(userName.c_str());
    if(pwd != NULL){
        uid = pwd->pw_uid;
    }
    return uid;
}

vector<string> getAllProcessPid() {
    vector<string> allProcessPid;
    //打开目录 /proc
    DIR *dir = opendir("/proc");
    if(dir == NULL){
        return allProcessPid;
    }

    struct dirent *pid_dir;
    while(pid_dir = readdir(dir)){ 
        //是pid目录
        if((pid_dir->d_name)[0] <= '9' && (pid_dir->d_name)[0] >= '1'){
            allProcessPid.push_back(pid_dir->d_name);
        }
    }

    closedir(dir);
    return allProcessPid;
}

vector<Process> getUserAllProcess(string userName) {
    vector<Process> userAllProcess;
    uid_t uid = getUserUid(userName);
    if(uid==-1)return userAllProcess;
    //cout<<userName<<" uid is: "<<uid<<endl;
    vector<string> allProcessPid = getAllProcessPid();

    vector<string>::iterator it;
    for(it=allProcessPid.begin();it!=allProcessPid.end();++it) {
        string& pidStr = *it;
        string statusFile = "/proc/" + pidStr + "/status";
        string cmdlineFile = "/proc/" + pidStr + "/cmdline";
        int pid = atoi(pidStr.c_str());
        string name = "";
        string cmdline = "";

        ifstream ifs;
        ifs.open(statusFile.c_str(), ios::in);
        if(ifs.is_open()) {
            string tName = "";
            string line;
            getline(ifs, line);
            // Name:\t<name>
            int startPos = 6;
            tName = line.substr(startPos, line.size()-startPos);
            int index = -1;
            while(getline(ifs, line)) {
                index = line.find("Uid");
                if(index==0) {
                    // Uid:\t<uid>
                    index = 5;
                    string uidStr = "";
                    while(line[index]!='\t'&&index<line.size()) {
                        uidStr+=line[index++];
                    }
                    int tUid = atoi(uidStr.c_str());
                    if(tUid==uid) {
                        name = tName;
                    }
                    break;
                }
            }
        }
        ifs.close();
        if(name.empty()) continue;
        //cout<<pid<<" "<<name<<endl;

        ifs.open(cmdlineFile.c_str(), ios::in);
        if(ifs.is_open()) {
            string line;
            while(getline(ifs, line, '\0')) {
                if(cmdline!="")cmdline+=" ";
                cmdline += line;
            }
        }
        ifs.close();
        userAllProcess.push_back(Process(pid, uid, name, cmdline));
    }
    return userAllProcess;
}

bool hasKeyWords(const string& name, const string& cmdline, const vector<string>& keyWords) {
    bool flag = false;

    for(int i=0;i<keyWords.size();++i) {
        if(name.find(keyWords[i])!=-1||cmdline.find(keyWords[i])!=-1) {
            flag = true;
            break;
        }
    }

    return flag;
}

int main(int argc, char const *argv[])
{
    //判断参数是否合法
    if(argc < 3) {
        cout<<"killUserProc <userName> <keyWord1> <keyWord2> ..."<<endl;
        return 0;
    }
    string userName=argv[1];
    vector<string> keyWords;
    for(int i=2;i<argc;++i) {
        keyWords.push_back(argv[i]);
    }

    pid_t thisPid = getpid();
    vector<Process> userAllProcess = getUserAllProcess(userName);
    vector<Process>::iterator it;
    for(it=userAllProcess.begin();it!=userAllProcess.end();++it) {
        //cout<<it->_pid<<" "<<it->_name<<" "<<it->_cmdline<<endl;
        if(hasKeyWords(it->_name, it->_cmdline, keyWords)) {
            // pid:可能选择有以下四种
            // 1. pid大于零时,pid是信号欲送往的进程的标识。
            // 2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
            // 3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
            // 4. pid小于-1时,信号将送往以-pid为组标识的进程。
            // 为了防止误杀我加一个这个
            if(it->_pid<=0||it->_pid==thisPid)continue;

            int retval = kill(it->_pid, SIGKILL);  //发送SIGKILL信号给进程,要求其停止运行
            if (retval<0) {
                cout<<"failed kill "<<it->_pid<<" "<<it->_name<<" "<<it->_cmdline<<endl;
            } else {
                cout<<"success kill "<<it->_pid<<" "<<it->_name<<" "<<it->_cmdline<<endl;
            }
        }
    }

    return 0;
}

文章目录