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

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

ここに問題があります。私は比較的新しくインストールしたMint 19を実行しています。 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をアンインストール、削除、再インストールしてみましたが、同じ結果が得られました。完璧に動作し、一度だけこのエラーを見つめてもわかりません。

これはビジネスや他の何とも関係がなく、技術的に私はプログラムに参加している人ではありませんが、今、なぜプログラムが失敗するのか、どのようにプログラムを壊したのかを知りたいのです。これは無視するにはとても神秘的です。時間をいただきありがとうございます。

答え1

簡単に言うと:$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!"

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

dwarf-fortressUbuntuが提供するパッケージはPythonラッパーを使用します/usr/games/dwarf-fortress。このラッパーは、data他のディレクトリと共にインストールされる2番目のレベルの階層を作成します$XDG_DATA_HOME/.local/share/dwarf-fortress/run/.unionfs-fuseunionfs(8)

これにより、モードを$XDG_DATA_HOME/.local/share/dwarf-fortressディレクトリに配置できるため、何も変更する必要はありません/usr/share/games/dwarf-fortress。本当に良いです!ただし、unionfs慎重に取り扱い、適切に清掃する必要があります。ゲームの終了に慣れると、C-cPythonスクリプトはこれを実行できません。

したがって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-fuseinを削除してください$XDG_DATA_HOME/dwarf-fortress/run/。私はXDG_DATA_HOMEそのような設定をしていないので、誤って間違ったディレクトリを削除することがないようにを$HOME使用して確認する必要があります!env

rm -r $HOME/.local/share/dwarf-fortress/run/.unionfs-fuse

それはすべてです。df_linuxバージョンは参考にしてくださいベイ12ゲームPythonラッパーやUnionfsを使用していないため、この問題は発生しません。

という、問題が解決しました。2019年に発送されます。bullseye残念ながらいいえ修正されたため、0.44.12-1依然としてbuster影響を受ける可能性があります。

このソリューションをどう思いましたか?

最初に見てみると、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ドワーフポートレス終了後にマウント解除されたマウントがあるように見え、mount | grep unionfsでアクティブなマウントが確認されます/tmp。ディレクトリ全体$XDG_DATA_HOME/dwarf-fortressを削除しましたが、再び機能しました。合格してインストールをstrace -ff -e trace=execve dwarf-fortress確認し、ディレクトリを見つけることができました。unionfs.unionfs-fuse

関連情報