如何检查 Perl 脚本是否正在终端中运行?

发布于 2024-11-27 23:49:59 字数 680 浏览 3 评论 0原文

我试图在 Linux 上的 Perl 脚本中确定它是否在终端中运行。

也就是说,我需要的代码:

  • 仅在命令行上运行时返回 true
  • 运行 ./myscript.pl | 时也返回 true less 甚至 ./myscript.pl /dev/null 2>/dev/null
  • 在 cron 作业中运行或作为 CGI 运行时返回 false 特别是因为第二个项目符号

,我无法使用 -t STDOUT 和变体,而且 IO::Interactive 没有用。

该信息似乎确实可用。如果我运行 ps,它会在 TTY 列中显示类似 pts/2 的条目,即使我运行 ./myscript 也是如此。 pl /dev/null 2>/dev/null? 作为 cron 作业或 CGI 脚本运行时。

有没有一种优雅的方法可以在 Perl 脚本中确定这一点?我不想解析 ps 的输出。

I'm trying to determine, within a Perl script on Linux, whether it's running in a terminal.

That is, I need code that:

  • returns true when simply running on the command-line
  • also returns true when running ./myscript.pl | less or even ./myscript.pl </dev/null >/dev/null 2>/dev/null
  • returns false when running in a cron job, or as a CGI script

Especially because of the second bullet, I can't use -t STDOUT and variations, and also IO::Interactive is of no use.

The information does appear to be available. If I run ps, it shows an entry like pts/2 in the TTY column, even when I run ./myscript.pl </dev/null >/dev/null 2>/dev/null, and ? when running as a cron job or CGI script.

Is there an elegant way to determine this in a Perl script? I'd rather not have to parse the output of ps.

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

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

发布评论

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

评论(5

╰◇生如夏花灿烂 2024-12-04 23:49:59

你可以尝试打开/dev/tty。
如果您在终端中(甚至在远程计算机上的终端中),这将起作用。
否则,如果脚本通过 at 或 cron 运行,则不会。

注意:这仅适用于 Unix 系统。

You can try to open /dev/tty.
This will work if you are in a terminal (even in a terminal on a remote computer).
Otherwise, if the script is run via at or cron, it won't.

Note: this will only work on Unix systems.

青衫儰鉨ミ守葔 2024-12-04 23:49:59

我自己的问题的另一个答案。我研究了 ps 源代码,了解它如何确定 TTY,它使用 /proc/[pid]/stat

use strict;
use warnings;
use 5.010;
use autodie;

sub isatty()
{
    # See http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html
    open(my $stat, '<', "/proc/$/stat");
    if (<$stat> =~ m{^\d+\s+\(.*\)\s+\w\s+\d+\s+\d+\s+\d+\s+(\d+)}) {
        return $1 > 0;
    }
    else {
        die "Unexpected format in /proc/$/stat";
    }
}

Another answer to my own question. I studied the ps source to see how it determined the TTY, and it uses /proc/[pid]/stat.

use strict;
use warnings;
use 5.010;
use autodie;

sub isatty()
{
    # See http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html
    open(my $stat, '<', "/proc/$/stat");
    if (<$stat> =~ m{^\d+\s+\(.*\)\s+\w\s+\d+\s+\d+\s+\d+\s+(\d+)}) {
        return $1 > 0;
    }
    else {
        die "Unexpected format in /proc/$/stat";
    }
}
荒人说梦 2024-12-04 23:49:59

PS 应该可以帮助你。
PS 辅助 | grep '文件名.pl'

PS should help you out.
ps aux | grep 'filename.pl'

剧终人散尽 2024-12-04 23:49:59

为了部分回答我自己的问题,以下方法可以解决问题:

sub isatty()
{
    my $tty = `/bin/ps -p $ -o tty --no-headers`;
    $tty =~ s{[\s?]}{}g;
    return $tty;
}

如果有的话返回 TTY 名称(为真),如果没有则返回“”(假)。

我仍然更喜欢没有外部命令的解决方案......

To partially answer my own question, the following does the trick:

sub isatty()
{
    my $tty = `/bin/ps -p $ -o tty --no-headers`;
    $tty =~ s{[\s?]}{}g;
    return $tty;
}

Returns the TTY name if any (which is true), or "" if none (false).

I'd still prefer a solution without an external command...

帅的被狗咬 2024-12-04 23:49:59

首先,您必须检查输出是否通过 -t 与终端关联。当然,如果你愿意,你可以查看 /proc/$pid/fd/1 ,它是设备的符号链接。如果是终端的话你可以测试一下。

但如果还不够,你可以通过%ENV特殊哈希表来检查环境变量。 CGI-BIN 接口设置了其中一些。如果您在 cron 下运行脚本,它会设置一些变量。如果还不够,您可以在 /etc/crontab 文件中设置它并在脚本中进行测试。你要做的就是为了你的需要。

您应该只调用该完整过程一次。您无法迭代它,因为脚本环境不会改变,直到它开始工作。

您不必调用任何外部命令,也不需要特殊的 libarier。您所需要的只是 Windows 不兼容。但如果你使用的是windows10,那么它有类似于基于ubuntu的linux的环境。那么你就不能像你这样做那样强烈地关注win32api和类unix系统之间的兼容性。

At first you must check, output is associated with terminal by -t . Of course if you want, you can look at /proc/$pid/fd/1 , it is symlink to device. You can test it, if it is a terminal.

But if it is not enough, you can check enviromential variables by %ENV special hash table. CGI-BIN interface sets some of them. If you run script under cron, it sets some variable. If it is not enough, you can set it in /etc/crontab file and test in your script. It is for your needs what you'll do.

You should call that complete procedure only once. You cannot iterate it, because script environment won't change, until it is working.

You don't have to call any external commands, or you don't need special libarier. Only what you need, is windows incompatibilities. But if you are using windows10, then it has environment similar to linux based on ubuntu. then you cannot look out as strongly, as you do it making compatibility between win32api and unix like systems.

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