工作中有一个小需求,需要统计用户空间使用量
统计空间的主函数:
#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;
}