Я не согласен с текущими ответами. Выходной файл должен быть открыт до запуска команды, иначе команде не удастся записать свой вывод.
Это потому, что «все есть файл» в нашем мире. Выход на экран - SDOUT (также известный как дескриптор файла 1). Для приложения для записи на терминал он открывает fd1 и записывает его как файл.
Когда вы перенаправляете вывод приложения в оболочку, вы изменяете fd1, чтобы он фактически указывал на файл.
Но вам все это приятно сказать, но вы можете легко посмотреть, как это работает с strace.
strace sh -c "ls > ls.out" 2> strace.out
В strace.out мы можем видеть следующие основные моменты:
open("ls.out", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
Это открывает ls.out как fd3. Напишите только. Усекает (переписывает), если существует, в противном случае создается.
fcntl(1, F_DUPFD, 10) = 10
close(1) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
Это немного жонглирование. Мы шунтируем STDOUT (fd1) в fd10 и закрываем его. Это связано с тем, что мы ничего не выводим на реальный STDOUT с помощью этой команды. Он заканчивается дублированием дескриптора записи на ls.out и закрытием исходного.
stat("/opt/wine-staging/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/home/oli/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/local/sbin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/sbin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/usr/bin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/sbin/ls", 0x7ffc6bf028c0) = -1 ENOENT (No such file or directory)
stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=110080, ...}) = 0
Это поиск исполняемого файла. Урок, возможно, не имеет длинного пути;)
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f0961324a10) = 31933
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 31933
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=31933, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn() = 31933
dup2(10, 1) = 1
close(10) = 0
Затем выполняется команда, и родитель ждет. Во время этой операции любой STDOUT будет фактически сопоставлен с дескриптором открытого файла на ls.out. Когда ребенок выдает SIGCHLD, это говорит о завершении родительского процесса и возобновлении его.
Почему открывает много жонглирования? Нет, я тоже не совсем уверен.
Конечно, вы можете изменить это поведение. Вы можете буферизировать в память с чем-то вроде sponge, и это будет невидимым из текущей команды. Мы по-прежнему влияем на дескрипторы файлов, но не на вид файловой системы.
ls | sponge ls.out
Вероятно, LVDS не является правильным волшебным словом для этого конкретного компьютера. В противном случае ваша атака умна.
Я боюсь, что исправление будет перезапущено. Самый изящный AltCtl-F1, логин, затем
sudo /sbin/shutdown -r now
После перезапуска запустите
xrandr --query
Чтобы узнать, какая магия необходима вместо LVDS. Помните, что они могут измениться при обновлении видеодрайверов.
Вероятно, LVDS не является правильным волшебным словом для этого конкретного компьютера. В противном случае ваша атака умна.
Я боюсь, что исправление будет перезапущено. Самый изящный AltCtl-F1, логин, затем
sudo /sbin/shutdown -r now
После перезапуска запустите
xrandr --query
Чтобы узнать, какая магия необходима вместо LVDS. Помните, что они могут измениться при обновлении видеодрайверов.