プロセスをだましてファイルが存在しないと考えるにはどうすればよいですか?


31

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

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

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

このプログラムの特定のインスタンスをだまして構成ファイルが存在しないふりをするにはどうすればよいですか(プログラムを変更せずに)。フォームのラッパーを期待していますが、 pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...他のソリューションにもオープンです。


2
ファイルを読み取る権限のないユーザーとして実行できます。
プシモン14年

1
@psimonクラスターの「単なるユーザー」として、バッチジョブを実行する新しいユーザーを作成できません。しかし、それは賢いアイデアであり、より良い提案がなければ、私のためにクラスター管理者にバグを報告します。
ジェフリーボスブーム14年

または、最初に構成ファイルの名前を変更し、プログラムを実行してから構成ファイルの名前を再度変更するスクリプトをセットアップします。
プシモン14年

@psimon私はもっと明確だったと思います:バッチジョブがクラスターでスケジュールされるタイミングに応じて、プログラムをインタラクティブにバッチモードで同時に使用している可能性があります。
ジェフリーボスブーム14年

1
はい、動的にリンクされている場合は、LD_PRELOADフックを使用できます。これは、代替手段であるCよりも簡単です(Cを知っている場合は1〜2時間で実装できます)ptrace。また、おそらくfakechrootを使用してこれを行うこともできます(LD_PRELOADであると思います)。
デロバート14年

回答:


33

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

HOME=/nowhere your-program

今、あなたのプログラムはあなたのホームディレクトリに他のリソースを必要としているかもしれません。それらがどれであるかを知っていれば、そこに必要なリソースへのリンクを使用して、あなたのプログラムのために偽の家を準備することができます。

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

5
この答えは私の問題を解決するので、この質問のタイトルにある質問に対する完全な一般的な答えではありませんが、受け入れました。別の回答で説明されているように、プリロードフックはより一般的な(ただし、より高い労力でも)ソリューションです。
ジェフリーボスブーム14年

28

他のすべてが失敗した場合は、を使用し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;
  }
}

注:私はこのコードをテストしていませんerrno。また、この部品が機能することを100%確信できません。

やなどのfakeroot呼び出しに対してどのように行われるかを見てください。getuid(2)stat(2)

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

元の: ./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; 
  }
}

2

構成ファイルを邪魔にならないように移動し、ファイルを通常の宛先にコピーし、プログラムを実行し、終了時に削除する対話型のユースケース用のシェルスクリプトラッパーを記述します。


最近の編集を参照してください:バッチスケジューリングを制御していないため、プログラムを対話的に使用し、同時にバッチジョブの一部として使用している可能性があります。
ジェフリーボスブーム14年

1

これはunionfs / aufsで可能になるはずです。chrootプロセスの環境を作成します。実際のディレクトリを読み取り専用レイヤーとして使用し、その上に空のレイヤーを配置します。次に、unionfsボリュームをchroot環境内のそれぞれのディレクトリにマウントし、そこでファイルを削除します。プロセスはそれを表示しませんが、他のすべては表示します。


0

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

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

ln -s config.interactive config

その後、リンクを整理してください。


最近の編集を参照してください:バッチスケジューリングを制御していないため、プログラムを対話的に使用し、同時にバッチジョブの一部として使用している可能性があります。この回答は、手動またはスクリプトを使用してファイルを移動するのと基本的に同じです。
ジェフリーボスブーム14年

1
ど!もっと考えてタイプする必要があります。大規模なアプリケーションですか?chrootに転送して、そこから対話的に実行できますか?それはすべて、プログラムが対話するものに依存していると思います。また、必要なものすべてをchrootに入れることも非常に退屈な作業になる可能性があります。(私はそのオプションから自分自身について話したと思う!)
garethTheRed 14年

0

プログラムが構成ファイルをどのように使用するを正確に特徴づけている場合は、見落としています。多くのプログラム(などbashviすぐに起動時の構成ファイルをチェックします)。ファイルが存在する場合は、それを読み取って閉じます。これらのプログラムは、これらの初期化ファイルに再びアクセスすることはありません。あなたのプログラムがそのようなものであるなら、読み続けてください。

(名前を変更して)構成ファイルをまったく存在させないという回答を拒否したことは知っていますが、他の人が提案したことはありませんでした。バッチモードでプログラムを呼び出すときにこれを行います。

DELAY_TIME=1
REALPATH="~/.config/myprogram"
HOLDPATH="${REALPATH}.hold"

mv "$REALPATH" "$HOLDPATH"
(sleep "$DELAY_TIME"; mv "$HOLDPATH" "$REALPATH")&
myprogram

これにより、構成ファイルが邪魔にならないように移動されますが、実行中であっても1秒後に元に戻されmyprogramます。これにより、ファイルが使用できない非常に短い時間枠が作成されます。この時間枠でプログラムをインタラクティブに実行する可能性はどのくらいですか?(それを行っても、終了して再起動するだけで、構成ファイルはおそらく元の場所に戻ります。)

これにより、競合状態が発生します。プログラムがファイルを開くのに時間がかかりすぎる場合、実際のファイルを取得する可能性があります。これが問題になるほど頻繁に発生する場合は、DELAY_TIMEの値を増やしてください。


1
最悪の事態に陥る可能性があるものは何ですか?私は文字通りそれが起こるのを見てきました。生産中。
ヘンクランゲベルド14年

-1

Iステファンの答えのように、これはしますだますある任意のファイルを信じるように任意のプログラムを - (そののdentryが一時的に実際に空であるファイルを指しているため)

cat <./test.txt
###OUTPUT###
notempty

mount --bind /dev/null ./test.txt
cat <./test.txt
###NO OUTPUT###

umount ./test.txt
cat <./test.txt
###OUTPUT###
notempty

次のこともできます。

mount --bind ./someotherconfig.conf ./unwanted.conf

お望みなら。


これは基本的に、以前のいくつかの回答と同等です(ただし、これにはユーザーに特権が必要だと思います)。OPはプロセスをだますことを望まないため、これらの他の回答を拒否しました。彼は、プログラムのバッチ呼び出しをだますことを望みます。
スコット14年

@Scott-私は同意mvしません-これより前のすべての回答は、ファイルの変更に関するいくつかのバリエーションを推奨しました-これは、実際にファイルや他のファイルを切り捨てるなど、その歯牙に影響を与える以外の結果をもたらす可能性があります-これは何にも作用しません それでも、私はすべきunshareことをmount...私が推測する
mikeserv
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.