如何在Linux中隐藏Shell窗口?C语言跨平台开发技术求助
Linux下隐藏控制台窗口的实现方案
在Linux系统中没有Windows平台ShowWindow这类统一的窗口隐藏API,可通过以下两种方案实现需求:
方案1:脱离控制台后台运行
适合无需与控制台交互的场景,通过重定向标准IO到/dev/null并脱离终端会话实现:
#include <unistd.h> #include <fcntl.h> // 在else分支中添加 int fd = open("/dev/null", O_RDWR); if (fd != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > 2) close(fd); } // 彻底脱离当前终端会话 setsid();
方案2:通过X11 API隐藏终端窗口
针对带桌面环境的场景,可通过X11接口找到当前进程关联的终端窗口并最小化(隐藏):
需链接X11库(编译时加-lX11),实现代码如下:
#include <X11/Xlib.h> #include <X11/Xatom.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void hide_terminal_window() { Display *display = XOpenDisplay(NULL); if (!display) return; char tty_path[256]; snprintf(tty_path, sizeof(tty_path), "/proc/%d/fd/0", getpid()); char real_tty[256]; ssize_t len = readlink(tty_path, real_tty, sizeof(real_tty)-1); if (len == -1) { XCloseDisplay(display); return; } real_tty[len] = '\0'; char *term_name = strrchr(real_tty, '/') + 1; Window root = DefaultRootWindow(display); Window *windows; unsigned int num_windows; if (XQueryTree(display, root, &root, NULL, &windows, &num_windows)) { for (unsigned int i = 0; i < num_windows; i++) { char *window_name = NULL; XFetchName(display, windows[i], &window_name); if (window_name && strstr(window_name, term_name)) { XIconifyWindow(display, windows[i], DefaultScreen(display)); XFree(window_name); break; } if (window_name) XFree(window_name); } XFree(windows); } XCloseDisplay(display); }
整合后的完整代码
#include <stdio.h> #ifdef _WIN32 #include <windows.h> #else #include <X11/Xlib.h> #include <X11/Xatom.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #endif void do_stuff() { // 自定义业务逻辑 } void do_other_stuff() { // 自定义业务逻辑 } #ifdef __linux__ void hide_terminal_window() { Display *display = XOpenDisplay(NULL); if (!display) return; char tty_path[256]; snprintf(tty_path, sizeof(tty_path), "/proc/%d/fd/0", getpid()); char real_tty[256]; ssize_t len = readlink(tty_path, real_tty, sizeof(real_tty)-1); if (len == -1) { XCloseDisplay(display); return; } real_tty[len] = '\0'; char *term_name = strrchr(real_tty, '/') + 1; Window root = DefaultRootWindow(display); Window *windows; unsigned int num_windows; if (XQueryTree(display, root, &root, NULL, &windows, &num_windows)) { for (unsigned int i = 0; i < num_windows; i++) { char *window_name = NULL; XFetchName(display, windows[i], &window_name); if (window_name && strstr(window_name, term_name)) { XIconifyWindow(display, windows[i], DefaultScreen(display)); XFree(window_name); break; } if (window_name) XFree(window_name); } XFree(windows); } XCloseDisplay(display); } #endif int main(void) { do_stuff(); #ifdef _WIN32 ShowWindow(GetConsoleWindow(), SW_HIDE); #elif defined(__linux__) hide_terminal_window(); #endif while(1) { do_other_stuff(); } }
注意事项
- 方案2仅适用于X11桌面环境,纯字符终端(tty)下无效,此时建议用方案1
- 编译方案2的代码时需添加链接参数:
gcc your_code.c -o app -lX11 - 部分终端模拟器的窗口名称不包含pts编号,需调整窗口名称匹配逻辑适配
内容的提问来源于stack exchange,提问作者Tomatin
相关产品推荐
相关产品推荐

