web-dev-qa-db-ja.com

DwarfFortressのインストールに関する奇妙な問題

つまりね。私はMint19を実行していますが、比較的新しいインストールです。 Dwarf Fortressについて多くの誇大宣伝を聞いて、一度インストールしました。次に、急いで出発する必要があり、Control-Cで閉じました。それ以来、それを実行しようとするたびに、次の出力が得られます。

/tmp/dwarf-fortresss7j3cousrun/df: 6: /tmp/dwarf-fortresss7j3cousrun/df: ./libs/Dwarf_Fortress: not found
Traceback (most recent call last):
  File "/usr/games/dwarf-fortress", line 93, in <module>
    main()
  File "/usr/games/dwarf-fortress", line 90, in main
    run_df_in_unionfs_with_cleanup(user_run_dir, data_dirs, sys.argv)
  File "/usr/games/dwarf-fortress", line 60, in run_df_in_unionfs_with_cleanup
    run_df_in_unionfs(user_run_dir, data_dirs, args)
  File "/usr/games/dwarf-fortress", line 54, in run_df_in_unionfs
    run_df(tmp_dir, args)
  File "/usr/games/dwarf-fortress", line 46, in run_df
    subprocess.run(cmd).check_returncode()
  File "/usr/lib/python3.6/subprocess.py", line 369, in check_returncode self.stderr)
subprocess.CalledProcessError: Command '['/tmp/dwarf-fortresss7j3cousrun/df', '/usr/games/dwarf-fortress']'
returned non-zero exit status 127.

その後、プログラムは直ちに終了します。同じ結果を得るために、dwarf-fortressを削除し、パージし、再インストールしようとしました。一度だけ完全に正常に動作し、このエラーをじっと見つめている限り、理解できません。

それはビジネスクリティカルでも何でもありません、私は技術的にはプレーヤーでさえありません。しかし、なぜプログラムが失敗しているのか、そしてどのようにプログラムが壊れたのかを本当に知りたいです。未チェックのままにしておくのは謎が多すぎます。御時間ありがとうございます。

TL; DR:次のスクリプトを使用して、_$XDG_DATA_HOME_/_$HOME_を残りからクリーンアップし、前のunionfs

_#!/bin/sh
set -eu

echo Killing currently running Dwarf Fortress instances
killall -q -9 Dwarf_Fortress || true

echo Removing old Dwarf Fortress unionfs mounts and mount points
find /tmp/ -maxdepth 1 -name "dwarf-fortress*" \
  -printf "  Found %f\n" \
  \( -exec fusermount -u {} \; -o -true \) \
  -exec rmdir {} \;


UNIONFSDIR=${XDG_DATA_HOME:-"${HOME:?}/.local/share/"}dwarf-fortress/run/.unionfs-Fuse
if [ -d "$UNIONFSDIR" ]; then
  echo Removing old .unionfs-Fuse directory
  rm -r "$UNIONFSDIR"
fi
echo Done. Run dwarf-fortress and praise Armok!
_

なぜこれが起こるのですか?

Ubuntuが提供する_dwarf-fortress_パッケージはPythonラッパー_/usr/games/dwarf-fortress_を使用します。そのラッパーは_$XDG_DATA_HOME/.local/share/dwarf-fortress/run/.unionfs-Fuse_にセカンダリdata階層を作成します。他のいくつかのディレクトリと一緒にunionfs(8)としてマウントされます。

これにより、modを_$XDG_DATA_HOME/.local/share/dwarf-fortress_ディレクトリに配置できるため、_/usr/share/games/dwarf-fortress_の内容を変更する必要がなくなります。これはすばらしいことです。ただし、unionfsは慎重に扱い、正しくクリーンアップする必要があります。 Pythonスクリプトは、使用したときにそうすることができませんでした C-c ゲームから抜け出すために。

したがって、unionfsおそらくまだマウントされていますが、状態が悪いです。

どうすれば修正できますか?

したがって、まず、ゲームが完全に閉じていることを確認してください。

_killall -s KILL Dwarf_Fortress
_

次に、残りのunionfs DFマウント:

_mount | grep -a -e dwarf -e unionfs
unionfs on /tmp/dwarf-fortresswvlaptrarun type Fuse.unionfs (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
unionfs on /tmp/dwarf-fortress4ylv2t19run type Fuse.unionfs (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
_

ご覧のとおり、現在私のシステムには2つあります。両方とも壊れているので、_fusermount -u_でそれらを取り除きましょう:

_fusermount -u /tmp/dwarf-fortresswvlaptrarun 
fusermount -u /tmp/dwarf-fortress4ylv2t19run 
_

最後に、最も重要なのは、_.unionfs-Fuse_の_$XDG_DATA_HOME/dwarf-fortress/run/_を削除することです。 _XDG_DATA_HOME_を設定していないので、_$HOME_を使用する必要があります。誤って間違ったディレクトリを削除する前に、envを確認してください。

_rm -r $HOME/.local/share/dwarf-fortress/run/.unionfs-Fuse
_

それでおしまい。 Bay 12 Games の_df_linux_バージョンは、PythonラッパーもUnionfsも使用しないため、この問題は発生しないことに注意してください。

全体として、トラブルシューティングは面倒なので、この問題はバグレポートの価値があると思います。 _dwarf-fortress_ラッパーは、このケースを処理する_-clean_オプションを提供する必要があります。可能であれば、バグレポートを提出してください Debianアップストリーム上

このソリューションはどのようにして思いついたのですか?

まず、file $(which dwarf-fortress)を調べたところ、Pythonスクリプト:

_$ file $(which dwarf-fortress)
/usr/games/dwarf-fortress: Python script, ASCII text executable
_

次に、任意のエディターでスクリプトを確認したところ、

_def get_user_run_dir():
    old_run_dir = xdg.BaseDirectory.save_data_path('dwarf-fortress')
    new_run_dir = os.path.join(old_run_dir, 'run')

    ...

def run_df_in_unionfs(user_run_dir, data_dirs, args):
    mnt_dirs = user_run_dir + "=rw:" + ':'.join(data_dirs)
    with tempfile.TemporaryDirectory(suffix='run', prefix='dwarf-fortress') as tmp_dir:
        cmd = ['unionfs', '-o', 'cow,relaxed_permissions', mnt_dirs, tmp_dir]
        subprocess.run(cmd).check_returncode()
        try:
            run_df(tmp_dir, args)
        finally:
            subprocess.run(['fusermount', '-u', tmp_dir]).check_returncode()
_

これは、_xdg.BaseDirectory_に少なくとも何かが見つかったことを示しています。これは_$HOME/.local/share_です(特に設定されていない限り)。同時に、_fusermount -u_は、Dwarf Fortressを終了した後、保留中のアンマウントがあることを示し、_mount | grep unionfs_は_/tmp_でアクティブなマウントを確認しました。 _$XDG_DATA_HOME/dwarf-fortress_ディレクトリ全体を削除しましたが、再び機能しました。 _strace -ff -e trace=execve dwarf-fortress_を使用して、unionfsマウントを確認し、_.unionfs-Fuse_ディレクトリを見つけることができました。

4
Zeta