ファイルが存在しないとプロセスに思わせるにはどうすればよいですか?

ファイルが存在しないとプロセスに思わせるにはどうすればよいですか?

設定を保存するプログラムがあり、~/.config/myprogramこれを対話型とバッチ キュー システムの両方で使用しています。対話型で実行しているときは、このプログラムで構成ファイルを使用するようにしています (実際に使用されています)。ただし、バッチ モードで実行しているときは、関連するすべての設定を上書きするコマンド ライン オプションを指定するため、構成ファイルは必要ありません。さらに、ネットワーク経由で構成ファイルにアクセスすると、プログラムの起動時間が数秒長くなります。ファイルが存在しない場合は、プログラムの起動がはるかに速くなります (各ジョブは約 1 分しかかからないため、バッチ ジョブのスループットに大きな影響を与えます)。ただし、このプログラムは対話型でも使用するため、構成ファイルを常に移動/削除したくはありません。バッチ ジョブがクラスターでスケジュールされるタイミング (他のユーザーの使用状況に基づく) によっては、プログラムを対話型で使用し、同時にバッチ ジョブの一部として使用したい場合があります。

(余談ですが、ネットワーク ファイルのパフォーマンスが非常に遅いのはおそらくバグですが、私はクラスターのユーザーなので、回避することしかできず、修正することはできません。)

バッチ使用のために、構成ファイルを読み取らない (または読み取らないようにするコマンドライン オプションがある) プログラムのバージョンをビルドすることもできますが、このプログラムのビルド環境は設計が不十分で、セットアップが困難です。システムのパッケージ マネージャーを通じてインストールされたバイナリを使用する方がはるかに望ましいです。

このプログラムの特定のインスタンスをだまして、設定ファイルが存在しないかのように見せかけるにはどうすればよいですか (プログラムを変更せずに)? フォームのラッパーを期待しています pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...が、他の解決策も検討します。

答え1

そのプログラムはおそらく からそのファイルへのパスを解決します$HOME/.config/myprogram。したがって、次のようにして、ホーム ディレクトリが別の場所にあることをプログラムに伝えることができます。

HOME=/nowhere your-program

さて、おそらく your-program はホーム ディレクトリに他のリソースを必要とします。それが何かがわかっている場合は、そこにある必要なリソースへのリンクを含む your-program 用の偽のホームを準備できます。

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram

答え2

LD_PRELOAD他のすべてが失敗した場合は、呼び出しがインターセプトされ、他の呼び出しが通過するように、挿入に使用するラッパー ライブラリを作成しますopen("/home/you/my-program/config.interactive")。これは、システム コールをフィルターするため、シェル スクリプトを含むあらゆるタイプのプログラムで機能します。

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

注: このコードはテストしていないので、この部分が機能するかどうかは 100% 確実ではありませんerrno

どのようにfakerootgetuid(2)およびのような呼び出しに対してこれを行いますstat(2)

基本的に、リンカーはそのアプリケーションをライブラリにリンクし、シンボルをオーバーライドします。独自のライブラリでopen指定された 2 つの異なる関数を使用することはできないため、2 番目の部分 (例) で分離して、元の呼び出しにリンクする必要があります。openget_real_openopen

オリジナル:./Application

Application -----> libc.so
            open()

傍受:LD_PRELOAD=yourlib_wrap.so ./Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

編集:どうやらld有効にできるフラグ ( )があり--wrap <symbol>、これにより二重リンクに頼ることなくラッパーを記述できます。

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}

答え3

設定ファイルを移動し、対話型ユースケース用のシェル スクリプト ラッパーを作成します。このシェル スクリプト ラッパーは、ファイルを通常の宛先にコピーし、プログラムを実行し、終了時にファイルを削除します。

答え4

設定ファイルの名前を eg に変更しますconfig.interactive。 eg という名前の別の空のファイルを作成しますconfig.script

config次に、必要な実際の構成への (またはアプリケーションが構成ファイルとして期待する名前)というソフト リンクを作成し、アプリケーションを実行します。

ln -s config.interactive config

後でリンクを整理することを忘れないでください。

関連情報