web-dev-qa-db-ja.com

`/ proc / $ PID / cwd`:POSIXに相当するものはありますか?

Linuxには/procディレクトリとファイルシステムは、私が知る限り、POSIXの一部ではありません。それぞれの/proc/$PID subdirectoriesは、このPIDのプロセスの実際の作業ディレクトリを指すシンボリックリンクcwdです(cwdリンクは常に最新です)。

このシンボリックリンクは、個別のシェルを操作したり、2つのシェル(正式には作業ディレクトリ)間でファイルを交換したりするなど、一部のユースケースに便利です。

POSIX機能のみを使用して、同様のものを取得する簡単な方法はありますか?

質問の詳細

コメントの後、より正確に:必ずしもリンクおよび環境変数である必要はありませんlile $<PID>_CWD、最初はため息をつきましたが、そのような解決策は存在しないと思いますが、それでも同じくらい問題ありません。参照しやすく(シンボリックリンクや環境変数など)、他のプロセスが作業ディレクトリを切り替えるたびに常に最新である必要があります。

ソリューションは必ずしもPOSIXである必要はなく、最も重要な側面は移植性ですが、POSIXは確かに保証です。

8
Hibou57

lsofを使用するソリューションがあります。デフォルトではBSDにインストールされていないため、BSDで使用したい場合は、インストールする必要があります。

シェルスクリプトを作成します。

#!/bin/sh
lsof -p $1 | grep cwd | awk '{print $9}'

パス内のディレクトリにコピーします。最初の引数で指定されたPIDの作業ディレクトリを出力します。

$ script 1987
/home/enedil
6
enedil

POSIXは、無関係なプロセスに関する情報を取得するという点ではあまり提供していません。本当に ps しかなく、現在のディレクトリに関する情報は提供されません。経営幹部レベルのAPIはこれ以上優れていません(実際、psによって取得される情報のほとんどは、その出力を解析することによってのみ取得できます¹)。

おかしなことに、POSIXは、逆方向に移動するための移植可能な方法を提供します。ファイルが与えられた場合、 fuser を呼び出すことで、どのプロセスがファイルを開いているかを確認できます。次のスニペットは、特定の作業ディレクトリを持つプロセスのPIDを示しています。

fuser -f "$directory_name" 2>&1 | sed -e '$!d' -e 's/.*://' -e 's/  */\
/' | sed -n 's/c$//p'

実際に移植可能な方法でプロセスに関する情報が必要な場合は、 lsof を使用してください。 lsofの作成者は、さまざまなUNIXバリアントに関する情報を取得するさまざまな方法をすべて実装する作業を行っています。

カジュアルブラウジングの場合:

lsof -a -p "$pid" -d cwd

自動解析の場合:

lsof -a -p "$pid" -d cwd -F n | sed -e '1d' -e '2s/^n//'

lsofは、改行を文字列\nに置き換えることに注意してください。

一部のUnixバリアントは、サードパーティソフトウェアを必要としないメソッドを提供しますが、これらのメソッドは、各バリアントに固有のPERFORCEになります。非常に関連する注記については、 ファイル記述子リンクの移植性 を参照してください。

¹ 一部の古いユニスにはps setuid rootがあり、カーネルメモリを読み取るため、このsetuidバイナリを使用することがこの情報を取得する唯一の方法でした。

私は自分の答えを提供します。

インタラクティブシェルのコンテキストでのオプション(質問はこのコンテキストに焦点を当てています)は、Bashが提供する自動化の機会を使用して、/proc/$PID/cwdのリンクを自動的に維持することができます。

Prompt_COMMAND="ln -sfT \$(pwd) ~/$LINK_NAME"

リンクは頻繁に上書きされるため、fオプションが必要です。 Tオプションは必須です。そうでない場合、fオプションは正しく機能するようです。

シェルは、たとえば~/.bashrcでこれを使用して、協調的にすることができます。

if [ -v CWD_LINK_NAME ]; then
   Prompt_COMMAND='ln -sfT "$(pwd)" "'$CWD_LINK_NAME'";'$Prompt_COMMAND
   declare -r CWD_LINK_NAME
   function rm_cwd_link() {
      rm "$CWD_LINK_NAME"
   }
   trap rm_cwd_link EXIT
fi

シェルまたは端末は、CWD_LINK_NAMEを関連する任意の値に設定して実行できます。例CWD_LINK_NAME="~/$SOME_ROLE_NAME" gnome-terminal

別の方法は、同じ概念を使用して変数内の梨の作業ディレクトリを追跡することです。この追跡は、 @ Gilles@ enedil の両方の貢献に基づいています。

Prompt_COMMAND="PEAR_WD=\$(lsof -p $PID | awk '/cwd/{print \$9}')"

ただし、これは精度と利便性が低く、まれなケースでは$Prompt_COMMANDを他のシェルで設定できない唯一の方法である可能性があります。

私は最初のオプションに賛成です(他に貢献がある場合は、答えを選択する前にまだ待っています)。

0
Hibou57