c++写一个查询工作站服务器中每个用户的空间使用量

工作中有一个小需求,需要统计用户空间使用量

统计空间的主函数:

#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <string>
#include <cstdlib>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <vector>
#include <cstring>
#include <thread>
#include <mutex>

// 获取所有用户的home目录
std::vector<std::string> getUsersHomeDirectories() {
    std::vector<std::string> homeDirs;
    struct passwd *pw;
    while ((pw = getpwent()) != NULL) {
        if (pw->pw_dir) {
            homeDirs.push_back(pw->pw_dir);
        }
    }
    endpwent();
    return homeDirs;
}

// 运行系统命令并获取输出
std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        result += buffer.data();
    }
    return result;
}

// 获取单个用户目录的磁盘使用量
void getDiskUsage(const std::string& dir, std::map<std::string, long>& usage, std::mutex& mtx) {
    std::string cmd = "du -sb " + dir + " | cut -f1";
    std::string output = exec(cmd.c_str());
    long size = std::stol(output);
    std::lock_guard<std::mutex> lock(mtx);
    usage[dir] = size;
}

int main() {
    std::vector<std::string> homeDirs = getUsersHomeDirectories();
    std::map<std::string, long> usage;
    std::mutex mtx;

    std::vector<std::thread> threads;
    for (const auto& dir : homeDirs) {
        threads.emplace_back(getDiskUsage, std::ref(dir), std::ref(usage), std::ref(mtx));
    }

    for (auto& th : threads) {
        if (th.joinable()) {
            th.join();
        }
    }

    std::cout << "User Directory Disk Usage:\n";
    for (const auto& pair : usage) {
        std::cout << pair.first << ": " << pair.second << " bytes\n";
    }

    return 0;
}

可重复使用线程的线程池:

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>

class ThreadPool {
public:
    ThreadPool(size_t threads);
    ~ThreadPool();

    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) 
        -> std::future<typename std::result_of<F(Args...)>::type>;

private:
    // 工作线程函数
    void worker();

    // 线程池中的线程
    std::vector<std::thread> workers;
    // 任务队列
    std::queue<std::function<void()>> tasks;

    // 同步
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;
};

ThreadPool::ThreadPool(size_t threads)
    : stop(false) {
    for(size_t i = 0; i < threads; ++i) {
        workers.emplace_back([this] { this->worker(); });
    }
}

ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        stop = true;
    }
    condition.notify_all();
    for(std::thread &worker: workers) {
        worker.join();
    }
}

void ThreadPool::worker() {
    while(true) {
        std::function<void()> task;
        {
            std::unique_lock<std::mutex> lock(this->queue_mutex);
            this->condition.wait(lock, [this]{ return this->stop || !this->tasks.empty(); });
            if(this->stop && this->tasks.empty()) {
                return;
            }
            task = std::move(this->tasks.front());
            this->tasks.pop();
        }
        task();
    }
}

template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) 
    -> std::future<typename std::result_of<F(Args...)>::type> {
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared<std::packaged_task<return_type()>>(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);

        // don't allow enqueueing after stopping the pool
        if(stop) {
            throw std::runtime_error("enqueue on stopped ThreadPool");
        }

        tasks.emplace([task](){ (*task)(); });
    }
    condition.notify_one();
    return res;
}

测试点:

#include <iostream>
#include <chrono>

int main() {
    ThreadPool pool(4);

    auto result1 = pool.enqueue([](int answer) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        return answer;
    }, 42);

    auto result2 = pool.enqueue([](int answer) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        return answer;
    }, 24);

    std::cout << "Result 1: " << result1.get() << std::endl;
    std::cout << "Result 2: " << result2.get() << std::endl;

    return 0;
}

两者的结合:

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <mutex>
#include <thread>
#include <functional>
#include <future>

// 线程池类的实现(与前面的实现相同)
// ...(省略前面的ThreadPool类实现)

// 获取所有用户的home目录
std::vector<std::string> getUsersHomeDirectories() {
    std::vector<std::string> homeDirs;
    struct passwd *pw;
    while ((pw = getpwent()) != NULL) {
        if (pw->pw_dir) {
            homeDirs.push_back(pw->pw_dir);
        }
    }
    endpwent();
    return homeDirs;
}

// 运行系统命令并获取输出
std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        result += buffer.data();
    }
    return result;
}

// 获取单个用户目录的磁盘使用量
long getDiskUsage(const std::string& dir) {
    std::string cmd = "du -sb " + dir + " | cut -f1";
    std::string output = exec(cmd.c_str());
    return std::stol(output);
}

int main() {
    std::vector<std::string> homeDirs = getUsersHomeDirectories();
    std::map<std::string, long> usage;
    std::mutex mtx;

    ThreadPool pool(8);

    std::vector<std::future<long>> results;
    for (const auto& dir : homeDirs) {
        results.emplace_back(pool.enqueue([&dir]() {
            return getDiskUsage(dir);
        }));
    }

    for (size_t i = 0; i < homeDirs.size(); ++i) {
        usage[homeDirs[i]] = results[i].get();
    }

    std::cout << "User Directory Disk Usage:\n";
    for (const auto& pair : usage) {
        std::cout << pair.first << ": " << pair.second << " bytes\n";
    }

    return 0;
}

自己实现发送email的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

class EmailSender {
public:
    bool sendEmail(const std::string& to, const std::string& from, 
                   const std::string& subject, const std::string& html_content) {
        std::string emailContent = "To: " + to + "\n" +
                                   "From: " + from + "\n" +
                                   "Subject: " + subject + "\n" +
                                   "Content-Type: text/html; charset=UTF-8\n\n" +
                                   html_content;

        // 将邮件内容写入临时文件
        std::string tempFileName = "/tmp/email.txt";
        std::ofstream emailFile(tempFileName);
        if (!emailFile.is_open()) {
            std::cerr << "Failed to create temporary email file." << std::endl;
            return false;
        }
        emailFile << emailContent;
        emailFile.close();

        // 使用系统命令发送邮件
        std::string command = "sendmail -t < " + tempFileName;
        int result = std::system(command.c_str());
        
        // 删除临时文件
        std::remove(tempFileName.c_str());

        return result == 0;
    }
};

int main() {
    EmailSender emailSender;

    std::string to = "recipient@example.com";
    std::string from = "sender@example.com";
    std::string subject = "Test Email";
    std::string html_content = "<html><body><h1>Hello, World!</h1></body></html>";

    if (emailSender.sendEmail(to, from, subject, html_content)) {
        std::cout << "Email sent successfully!" << std::endl;
    } else {
        std::cout << "Failed to send email." << std::endl;
    }

    return 0;
}
相关推荐
pk_xz12345618 分钟前
Shell 脚本中变量和字符串的入门介绍
linux·运维·服务器
小珑也要变强20 分钟前
Linux之sed命令详解
linux·运维·服务器
海绵波波10727 分钟前
Webserver(4.3)TCP通信实现
服务器·网络·tcp/ip
九河云2 小时前
AWS账号注册费用详解:新用户是否需要付费?
服务器·云计算·aws
Lary_Rock2 小时前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
幺零九零零3 小时前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
云飞云共享云桌面4 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端