Вы можете переместить определенный VT в другой заголовок с помощью con2fb
( исходный код, также в первой ссылке, а также ниже, в случае, если эти ссылки испаряются). Затем вы используете con2fb /dev/fb1 /dev/tty2
для перемещения TTY2 во второй кадровый буфер.
Возможным недостатком этого является то, что старый монитор (в данном случае ваш портретный монитор) больше не принимает ввод. Тем не менее, я не уверен, как можно сместить фокус между терминалами, не используя что-то вроде Alt+ F1 или Ctrl+ Alt+ F1, так что это довольно незначительный недостаток.
См. Также: LinuxQuestions и LWN, которые, несмотря на их возраст, также пытаются ответить на этот вопрос (также здесь, в случае, если первая ссылка исчезнет). Пост LWN угрожает страшными предупреждениями, если вы попытаетесь запустить X после этого, но также обсуждает, что множественные патчи кадрового буфера еще не в ядре, так что это несколько устарело.
con2fb.c
:
/* This is a userspace utility which allows you to redirect the console to another framebuffer device. You can specify devices & consoles by both numbers and devices. Framebuffers numbers are zero-based (/dev/fb0, ...), while consoles are one-based (/dev/tty1, ...). Original source: https://www.dafyddcrosby.com/dual-framebuffers/ Slightly updated from the original by Ben Stern to fix some minor warnings. License: GPL v2. Compile with: gcc -O2 -Wall -Werror -o con2fb con2fb.c */ #include <errno.h> #include <linux/fb.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int argc, char* argv[]) { struct fb_con2fbmap c2m; char* fbPath; u_int32_t con, fb; char* e; char* progname; struct stat sbf; int rv = 0; int f = -1; progname = strrchr(argv[0], '/'); if (progname != NULL) { progname++; } else { progname = argv[0]; } if (argc < 3) { fprintf(stderr, "usage: %s fbdev console\n", progname); return ENOENT; } do { fb = strtoul(argv[1], &e, 10); if (*e) { if (stat(argv[1], &sbf) < 0) { rv = errno; fprintf(stderr, "%s: Can't stat %s: %s\n", progname, argv[1], strerror(errno)); break; } if (!S_ISCHR(sbf.st_mode)) { fprintf(stderr, "%s: %s isn't a character device!\n", progname, argv[1]); rv = EINVAL; break; } fb = sbf.st_rdev & 0xFF; if (fb >= 32) { fb >>= 5; } fbPath = argv[1]; } else { fbPath = "/dev/fb0"; } con = strtoul(argv[2], &e, 10); if (*e) { if (stat(argv[2], &sbf) < 0) { rv = errno; fprintf(stderr, "%s: Can't stat %s: %s\n", progname, argv[2], strerror(errno)); break; } if (!S_ISCHR(sbf.st_mode)) { fprintf(stderr, "%s: %s isn't a character device!\n", progname, argv[2]); rv = EINVAL; break; } con = sbf.st_rdev & 0xFF; } c2m.console = con; c2m.framebuffer = fb; f = open(fbPath, O_RDWR); if (f < 0) { rv = errno; fprintf(stderr, "%s: Can't open %s: %s\n", progname, fbPath, strerror(errno)); break; } if (ioctl(f, FBIOPUT_CON2FBMAP, &c2m)) { rv = errno; fprintf(stderr, "%s: Can't set console mapping: %s\n", progname, strerror(errno)); break; } } while (0); if (f >= 0) { close(f); } return rv; }