`tail -f / proc / $ pid / fd / 1`できないのはなぜですか?


10

私はechoそのPID を示す簡単なスクリプトを書きました。

#/bin/bash

while true; do
    echo $$;
    sleep 0.5;
done

私は38441つのターミナルで上記のスクリプト(何度も何度も言う)を実行してtailおり、別のターミナルでファイル記述子を試行しています。

$ tail -f /proc/3844/fd/1

画面には何も表示されず、までハングし^cます。どうして?

また、すべてのSTDファイル記述子(IN / OUT / ERR)は同じptsにリンクしています。

$ ls -l /proc/3844/fd/
total 0
lrwx------ 1 mg mg 64 sie 29 13:42 0 -> /dev/pts/14
lrwx------ 1 mg mg 64 sie 29 13:42 1 -> /dev/pts/14
lrwx------ 1 mg mg 64 sie 29 13:42 2 -> /dev/pts/14
lr-x------ 1 mg mg 64 sie 29 13:42 254 -> /home/user/test.sh
lrwx------ 1 mg mg 64 sie 29 13:42 255 -> /dev/pts/14

これは正常ですか?

Ubuntu GNOME 14.04を実行しています。

この質問がULではなくSOまたはSUに属していると思われる場合は、教えてください。


回答:


13

作るstraceのをtail -f、それはすべてを説明しています。興味深い部分:

13791 fstat(3, {st_mode=S_IFREG|0644, st_size=139, ...}) = 0
13791 fstatfs(3, {...}) = 0
13791 inotify_init()                    = 4
13791 inotify_add_watch(4, "/path/to/file", IN_MODIFY|IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF) = 1
13791 fstat(3, {st_mode=S_IFREG|0644, st_size=139, ...}) = 0
13791 read(4, 0xd981c0, 26)             = -1 EINTR (Interrupted system call)

それは何ですか?inotifyファイルへのハンドラを設定し、このファイルで何かが発生するまで待機します。カーネルがtailこのinotifyハンドラーを介して、ファイルが変更された(通常は追加された)と言った場合、tail1)シーク2)変更を読み取ります3)それらを画面に書き込みます。

/proc/3844/fd/1システム上の/dev/pts/14は、キャラクターデバイスであるへのシンボリックリンクです。そこからアクセスできる「メモリマップ」のようなものはありません。したがって、アクセスできるディスクまたはメモリ領域がないため、inotifyに変更を署名できるものはありません。

このキャラクターデバイスは仮想端末であり、ネットワークソケットのように機能します。この仮想端末で実行されているプログラムは、(tcpポートにtelnetで接続した場合と同様に)このデバイスに接続し、書き込みたいものを書き込みます。画面のロック、端末制御シーケンスなど、複雑なものもありioctl()ます。これらは通常、呼び出しによって処理されます。

どういうわけか仮想端末を見たいと思う。これはLinuxで実行できますが、それほど単純ではなく、いくつかのネットワークプロキシのような機能と、これらのioctl()呼び出しを少しトリッキーに使用する必要があります。しかし、それを行うことができるツールがあります。

現在、どのdebianパッケージにこの目的のためのツールが含まれているのか思い出せませんが、少しグーグルすると、おそらく簡単に見つけることができます。

拡張子: @Jajeshがここで言及したように(私に与えた場合は+1を与える)、ツールの名前はwatchです。

拡張#2: @kelnosが言及され、シンプルcat /dev/pts/14でも十分でした。私はそれを試しました、そしてはい、それはうまくいきました、しかし正しくはありませんでした。私は多くのことを実験しませんでしたが、その仮想端末への出力がコマンドまたは元の場所のいずれかcat行き渡り、両方には行き渡らなかったように見えます。しかし、確かではありません。


peterhの答えtailは正しい(inotifyウォッチビット)が、彼は間違っています。つまり、必要なことを実行するのは非常に簡単です。単にのcat代わりに使用するだけですtail
ケルノス2014

@kelnosおかげで、私はそれを試して、結果で私の答えを拡張します。
peterh-モニカを復活させる

@kelnos catも私にとっては機能しません。tail と同じようにハングしctrl+cます。
cprn

1
まだわかりません。私が変更echo $$したecho $$ >> fooので、ファイルがあり、プロセスがそれを開き、0.5秒ごとに追加します。それでも、ファイル記述子とすべてのファイル記述子/proc/$pid/fd/(ただし、test.shスクリプト自体にリンクしている254 )からへのリンクを使用してアクセスすることはできません/dev/pts/14。bashはどのようfooに書き込みにアクセスしますか?
cprn 14

1
奇妙なことに、それはいくつかの状況でのみ機能するように見えます。問題のスクリプトを使用しても機能しません。しかし、シェルで "echo $$"を実行し、別のシェルでそのpidにFD 1をキャットすると、最初のシェルで入力したすべてが2番目のシェルでエコーされます。
ケルノス2014

4

のファイル/dev/ptsは通常のファイルではなく、仮想端末のハンドルです。pts読み書きのための動作は対称的ではない(そこに書かれているものであり、その後に通常のファイルまたはFIFO /パイプのように、そこから読み取ることができます)が、仮想端末を作成したプロセスによって媒介:いくつかの一般的なものですxtermまたはsshまたはagettyまたはscreen。制御プロセスは通常、ptsファイルを読み取るプロセスにキープレスをディスパッチし、それらがに書き込む内容を画面にレンダリングしますpts

したがって、tail -f /dev/pts/14は、スクリプトを開始したターミナルでタップしたキーを出力し、実行echo meh > /dev/pts/14すると、mehメッセージがターミナルに表示されます。


私がptsデバイスに書き込むことはできますが、そこから読み取ることができないようです。のように:tail -f /dev/pts/14その端末でタップしたキーを印刷しません。しかし、それは興味深い答えです。ありがとう。
cprn 14

0

私が見つかりました。いくつかの時間前にちょっとすることを回避時々 、あなたが持っていると仮定し、STDOUTに出力されているものをチェックする必要性に答えるpidプロセスのを、あなたが目に非友好的な結果を産んだことができます。

sudo strace -p $pid 2>&1 | grep write\(

-2

これについては、テーリングではなく、出力を監視する必要があると思います。

$ watch -n2 ls -l /proc/3844/fd/

これがあなたが必要とするものであることを願っています。


3
このコマンドは、標準出力のコンテンツ出力ではなく、2秒ごとに開いているfdsのリストを表示します。
アンゲル14

アンゲル、本当です。猫と一緒に時計を使用して、監視したい記述子の結果を確認できます。@ peter-horvathは、質問に対して完璧な説明をしたと思います。
Jayesh 2014

わかってるよwatch。私がやろうとしているのは、すでに実行中のプロセスの出力を確認することですので、watch役に立ちません。
cprn 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.