ZBLOG

不是简单的重定向,是控制终端的改变

改变进程的控制终端(Controlling Terminal)并绑定到 /dev/console,需通过系统调用或工具直接修改进程与终端的关联关系。以下是几种深度操作方法:


1. 使用 setsid + ioctl(TIOCSCTTY)(C 程序实现)

通过编程调用 setsid 创建新会话,再通过 ioctl 设置控制终端:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main() {
    int fd;
    
    // 1. 创建新会话(脱离原控制终端)
    if (setsid() == -1) {
        perror("setsid failed");
        return -1;
    }

    // 2. 打开目标终端设备(/dev/console)
    fd = open("/dev/console", O_RDWR);
    if (fd < 0) {
        perror("open /dev/console failed");
        return -1;
    }

    // 3. 强制设置控制终端(需要root权限)
    if (ioctl(fd, TIOCSCTTY, NULL) == -1) {
        perror("ioctl(TIOCSCTTY) failed");
        close(fd);
        return -1;
    }

    // (可选)重定向标准输入输出到控制台
    dup2(fd, STDIN_FILENO);
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);

    printf("Now attached to /dev/console\n");
    
    while(1); // 保持进程运行
}

编译运行

gcc set_console.c -o set_console
sudo ./set_console   # 必须root权限执行

2. 使用 reptyr 工具动态迁移

将已运行的进程转移到新的控制终端(需安装工具):

# Ubuntu/Debian安装
sudo apt install reptyr

# Step1: 启动后台进程(假设当前在tty1)
sleep infinity &

# Step2: 切换到目标终端(如tty2,按Ctrl+Alt+F2进入)
sudo reptyr $(pgrep sleep) </dev/console >/dev/console

限制

  • reptyr 对多线程进程支持有限。
  • /proc/sys/kernel/yama/ptrace_scope 需设置为 0(默认值)。

3. Systemd Service + TTYPath

在 systemd unit文件中显式声明控制终端:

[Service]
ExecStart=/path/to/your_program
StandardInput=tty
StandardOutput=tty
TTYPath=/dev/console      # 强制绑定到/dev/console 
TTYReset=yes              # 重置终端状态

# (关键选项)确保独立会话和终端控制权
UtmpIdentifier=%N         # Utmp记录标识符 
KillMode=process          # Kill时仅终止主进程 

生效命令

sudo systemctl daemon-reload && sudo systemctl start your-service.service 

4. Linux Kernel Hack(极端情况)

若需在早期用户态(如initramfs)中绑定,可修改内核代码或通过 init=参数传递自定义脚本:

// kernel启动参数示例:init=/my_init_script.sh

#!/bin/sh 
exec >/dev/console </dev/null 
echo "Hello from /dev console!" 
/sbin/getty -L ttyS0 vt100   # (示例)拉起getty登录界面 

验证方法

检查进程是否成功绑定到 /dev console:

方法一:查看 /proc/<PID>/stat

pid=$(pgrep your_program)
cat /proc/$pid/stat | cut -d ' ' -f7   # TTY编号字段(非0表示已绑定)

方法二:检查会话ID与控制台

ps -o sid,tty,cmd -p $pid   # SID应与TTY对应列一致  
ls -l /proc/$pid/fd/{0..2}   # FD应指向/dev console  

常见问题解决

Q1: Operation not permitted

  • 原因: SELinux、AppArmor或内核限制。
  • 解决:
       
    sudo setenforce Permissive       #临时关闭SELinux   
    echo "kernel.yama ptrace scope=0" >> etc sysctl conf && sysctl-p   
    

Q2: TIOCSCTTY失败但无报错?

  • 可能原因: / dev console未正确初始化为有效终端设备。
  • 调试步骤:
         
    stty sane </ dev console         #重置终端设置     
    dmesg | grep tty                #检查内核日志是否有异常     
    

以上方法覆盖了从用户态到内核层的多种场景,根据实际需求选择即可!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=8213

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?