写入 STDOUT 和打开“/dev/tty”的文件句柄有什么区别?

发布于 2024-10-11 17:57:48 字数 432 浏览 4 评论 0原文

这两个例子有什么区别?

#!/usr/bin/perl
use warnings;
use 5.012;
my $str = "\x{263a}";


open my $tty, '>:encoding(utf8)', '/dev/tty' or die $!;
say $tty $str;
close $tty;

open $tty, '>:bytes', '/dev/tty' or die $!;
say $tty $str;
close $tty;

# -------------------------------------------------------

binmode STDOUT, ':encoding(utf8)' or die $!;
say $str;

binmode STDOUT, ':bytes' or die $!;
say $str;

What are the differences between this two examples?

#!/usr/bin/perl
use warnings;
use 5.012;
my $str = "\x{263a}";


open my $tty, '>:encoding(utf8)', '/dev/tty' or die $!;
say $tty $str;
close $tty;

open $tty, '>:bytes', '/dev/tty' or die $!;
say $tty $str;
close $tty;

# -------------------------------------------------------

binmode STDOUT, ':encoding(utf8)' or die $!;
say $str;

binmode STDOUT, ':bytes' or die $!;
say $str;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

澉约 2024-10-18 17:57:48

不同之处在于,您正在写入两个不同并且(从 Perl 和您的程序的角度来看)独立文件句柄。

  • 第一个是在 Unixy 操作系统上打开一个特殊“设备”文件的文件句柄,它是“进程控制终端的同义词,如果有”(引自 此 Linux 文档)。请注意,虽然它通常被认为是“屏幕”,但它不一定是(例如,终端可以链接到串行端口的设备文件);它可能不存在或不可打开。

  • 第二个是默认与进程的文件描述符#1 关联的文件处理。

乍一看它们可能看起来是相同的,因为在典型情况下,Unix shell 默认情况下会将其文件描述符 #1(以及它在不重定向的情况下启动的每个进程之一)与 /dev 关联起来/tty

从 Perl 的角度来看,两者没有任何共同点,除了由于 Unix shell 的工作方式,这两者通常最终默认关联之外。

由于这种默认设置,两个引用的代码片段的功能行为通常看起来是相同的,但这只是“偶然”的。

实际差异包括:

  • /dev/tty 不一定存在于非 Unixy 操作系统上。因此使用 tty 是非常不可移植的。 Windows 等效项是 CON: IIRC。

  • 程序的

    STDOUT 可以由调用该程序的人关联(重定向)到任何内容。可以与一个文件相关联,也可以是到另一个进程的 STDIN 的管道。


您可以使用 -t 运算符

if ( -t STDOUT ) { say 'STDOUT is connected to a tty' }

另外,请注意,您可以通过显式关闭 STDOUT 文件句柄并重新打开它以指向 来确保 STDOUT 写入 /dev/tty >/dev/tty:

close STDOUT or die $!;
open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!;

The difference is that you are writing to two distinct and (from Perl's and your program's point of view) independent file handles.

  • The first one is a file handle opened to a special "device" file on Unixy OS which is "a synonym for the controlling terminal of a process, if any" (quote from this Linux document). Please note that while it is commonly thought of as "screen", it doesn't have to be (e.g. that terminal could be linked to a serial port's device file instead); and it may not exist or not be openable.

  • The second one is a file handled associated by default with file descriptor #1 for the process.

They may SEEM to be identical at first glance due to the fact that, in a typical situation, a Unix shell will by default associate its file descriptor #1 (and thus one of every process it launches without redirects) with /dev/tty.

The two have nothing in common from Perl point of view, OTHER than the fact that those two commonly end up associated by default due to the way Unix shells work.

The functional behavior of the two quoted pieces of code will often SEEM identical due to this default, but that is just "by accident".

Among practical differences:

  • /dev/tty does not necessarily exist on non-Unixy OSs. It's therefore highly un-portable to use tty. Windows equivalent is CON: IIRC.

  • STDOUT of a program can be associated (re-directed) to ANYTHING by whoever called the program. Could be associated to a file, could be a pipe to another process's STDIN.


You can CHECK whether your STDOUT is connected to a tty by using the -t operator:

if ( -t STDOUT ) { say 'STDOUT is connected to a tty' }

As another aside, please note that you CAN make sure that your STDOUT writes to /dev/tty by explicitly closing the STDOUT filehandle and re-opening it to point to /dev/tty:

close STDOUT or die $!;
open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!;
独木成林 2024-10-18 17:57:48

除了 DVK 所说的之外,您还可以通过说

perl -le 'open $o, ">:encoding(utf8)", "/dev/tty"; print "STDOUT"; print $o "/dev/tty"' > /dev/null

写入 STDOUT 转到 /dev/null 来看到简单的区别,但是写入 $o< /code> 转到屏幕。

In addition to what DVK said, you can see the simple difference by saying

perl -le 'open $o, ">:encoding(utf8)", "/dev/tty"; print "STDOUT"; print $o "/dev/tty"' > /dev/null

The write to STDOUT goes to /dev/null, but the write to $o goes to the screen.

风铃鹿 2024-10-18 17:57:48

从交互式 shell 启动的程序通常将标准输出写入终端,这会将 /dev/ttySTDOUT 呈现为同一目标。但在某些情况下,STDOUT 的输出可以写入其他目标。

STDOUT 可以路由到单独的文件:

perl someprogram.pl > a/file
perl someprogram.pl >> a/file

STDOUT 可以路由到另一个程序的输入

perl someprogram.pl | /usr/bin/mailx -s "Program Output" [email protected]

此外,该程序可以从非交互式 shell 启动,例如 cron作业或系统上运行的其他守护进程。这些程序的环境将无法访问 /dev/tty 设备,并且这些程序中的 STDOUT 将被路由到其他地方(或无处)。

A program launched from an interactive shell normally write standard output to a terminal, which would render /dev/tty and STDOUT as the same destination. But there are several circumstances where output to STDOUT could be written to some other destination.

STDOUT may be routed to a separate file:

perl someprogram.pl > a/file
perl someprogram.pl >> a/file

STDOUT may be routed to the input of another program

perl someprogram.pl | /usr/bin/mailx -s "Program Output" [email protected]

Also, the program could be launched from a non-interactive shell, like a cron job or from some other daemon running on your system. The environments for these programs will not have access to a /dev/tty device, and STDOUT in these programs will be routed somewhere else (or nowhere).

慕烟庭风 2024-10-18 17:57:48

1. stdout、stderr、stdin 是什么?它们是 fd/0、fd/1、fd/2

root@192-168-31-33:~# ls -alh /dev/std*
lrwxrwxrwx 1 root root 15 Apr 10 06:35 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Apr 10 06:35 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Apr 10 06:35 /dev/stdout -> /proc/self/fd/1

root@192-168-31-33:~# echo hello > /proc/self/fd/1
hello

2 的别名。 /dev/console 是什么? /dev/console 指向tty1 或ttyS0
tty

3. /dev/std{out, in, err} 和 tty* 设备之间有什么关系? 设备 /dev/std{out, in, err} 是一个tty* 设备的 wapper。

#include <unistd.h>
#include <stdio.h>
void print_tty(char* name, FILE * f) {
  printf("%s (fileno %d): ", name, fileno(f));
  if (isatty(fileno(f))) printf("TTY %s\n", ttyname(fileno(f)));
  else                   printf("not a TTY\n");
}
int main(void) {
  print_tty("stdin ", stdin);
  print_tty("stdout", stdout);
  print_tty("stderr", stderr);
}

输入图片此处描述
或者,一个更简单的例子:
输入图片此处描述

1. what stdout, stderr, stdin is? they are alias for fd/0, fd/1, fd/2

root@192-168-31-33:~# ls -alh /dev/std*
lrwxrwxrwx 1 root root 15 Apr 10 06:35 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Apr 10 06:35 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Apr 10 06:35 /dev/stdout -> /proc/self/fd/1

root@192-168-31-33:~# echo hello > /proc/self/fd/1
hello

2. what /dev/console is? /dev/console is pointed to tty1 or ttyS0.
tty

3.what relationship is between the /dev/std{out, in, err} and tty* devices? the devices /dev/std{out, in, err} are a wapper of tty* devices.

#include <unistd.h>
#include <stdio.h>
void print_tty(char* name, FILE * f) {
  printf("%s (fileno %d): ", name, fileno(f));
  if (isatty(fileno(f))) printf("TTY %s\n", ttyname(fileno(f)));
  else                   printf("not a TTY\n");
}
int main(void) {
  print_tty("stdin ", stdin);
  print_tty("stdout", stdout);
  print_tty("stderr", stderr);
}

enter image description here
or, a more simple example:
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文