Lorsque plusieurs hôtes Linux partagent un répertoire personnel Codex (~/.codex par défaut) via NFS (Network File System), ils risquent de corrompre une base de données SQLite s’ils l’ouvrent simultanément en mode de journalisation anticipée (WAL). Pour travailler en mode interactif dans la CLI ou dans Codex App via SSH, migrez le répertoire personnel partagé. Pour les traitements par lots indépendants, conservez le répertoire personnel Codex ou le répertoire SQLite de chaque hôte sur son disque local.
Pourquoi NFS peut poser problème à SQLite
Codex App et l’interface du terminal utilisent un index SQLite pour afficher la liste des conversations. Les bases de données stockent également les objectifs et l’état du traitement des mémoires. Sur un disque local, Codex utilise normalement le mode WAL. Des processus exécutés sur des hôtes différents ne peuvent pas partager la mémoire dont ce mode a besoin.
Lorsque Codex détecte un montage NFS sous Linux, il crée les bases de données en mode journal d’annulation (DELETE), qui utilise des verrous de fichiers. Migrez les bases de données WAL existantes avant de les ouvrir depuis un autre hôte.
Codex enregistre également les événements des conversations dans des fichiers rollout-*.jsonl. Ces fichiers peuvent déjà résider sur NFS, car un seul processus à la fois écrit dans chacun d’eux. La migration de SQLite laisse ces fichiers en place.
Migrer un répertoire personnel NFS existant
1. Vérifiez le répertoire personnel partagé
Exécutez codex --version sur chaque hôte, y compris sur tout serveur auquel vous vous connectez via SSH. Utilisez une version qui inclut codex migrate-nfs-db, par exemple Codex CLI 0.166.0. Vérifiez que tous les hôtes qui partagent ce répertoire personnel utilisent le même répertoire SQLite. Demandez à votre administrateur du stockage de vérifier qu’un verrou de fichier détenu sur un hôte empêche l’acquisition d’un verrou incompatible sur l’autre. Si le montage ne le permet pas, conservez SQLite sur le disque local.
Pendant la migration, ne définissez et ne modifiez ni le répertoire personnel SQLite ni le répertoire des journaux.
2. Arrêtez Codex sur chaque hôte
Terminez les échanges en cours, fermez l’application et la CLI, puis arrêtez les serveurs d’application distants, les démons en arrière-plan et les tâches planifiées qui utilisent ce répertoire personnel. Laissez-les tous à l’arrêt sur chaque hôte jusqu’à la fin de la migration. Une écriture concurrente risque de corrompre la base de données et d’entraîner la perte de modifications apportées aux objectifs ou aux mémoires.
Les enregistrements de session sont des fichiers distincts. Ils ne permettent pas de restaurer tout l’état de la base de données.
En mode démon, la CLI se connecte à un serveur qui continue de fonctionner en arrière-plan entre les sessions. Son socket Unix fonctionne uniquement sur l’hôte qui a démarré le serveur. Nous recommandons d’exécuter la CLI sans le démon lorsque plusieurs hôtes partagent un répertoire personnel Codex via NFS. Arrêtez le démon sur chaque hôte où il s’exécute avec codex app-server daemon stop.
Pour empêcher la CLI de le redémarrer, définissez daemon_auto_start sur false dans la section [features] de votre fichier config.toml partagé.
[features]
daemon_auto_start = false
Pour une seule session de la CLI, passez l’option --no-daemon. Cette option permet également d’utiliser la CLI sans passer par un démon déjà en cours d’exécution.
3. Lancez la migration
Pour chaque répertoire personnel Codex partagé, lancez la migration sur un seul hôte Linux. Utilisez le compte du propriétaire du répertoire et sa configuration habituelle. Laissez Codex à l’arrêt sur les autres hôtes jusqu’à la fin de la migration.
codex migrate-nfs-db
4. Reprenez une conversation
Si la commande affiche Skipped logs database, vérifiez où se trouve la base de données des journaux. Si elle se trouve sur un disque local, aucune autre intervention n’est nécessaire. Si elle se trouve sur NFS, vérifiez qu’elle utilise le mode de journalisation DELETE ou déplacez-la sur un disque local avant de rouvrir Codex sur un autre hôte.
Une fois la migration réussie, ouvrez le même projet sur un autre hôte avec le même compte utilisateur. Reprenez une conversation que vous connaissez dans l’application ou exécutez codex --no-daemon resume. Vérifiez que votre dernier échange s’affiche et que vous pouvez poursuivre la conversation.
Déplacer les journaux de diagnostic sur le disque local
Facultatif, recommandé après la migration. Les journaux de diagnostic vous aident à rechercher la cause des erreurs et des lenteurs au démarrage. Les écrire sur le disque local réduit le trafic NFS.
Sur chaque hôte, créez un répertoire privé dans lequel l’utilisateur peut écrire ses journaux. Définissez log_dir dans le fichier config.toml de l’utilisateur en indiquant le chemin absolu de son répertoire de journaux. Par exemple, Alice pourrait utiliser le réglage suivant.
log_dir = "/var/local/codex/alice/logs"
Les nouveaux journaux sont écrits dans ce répertoire. Les anciens restent à leur emplacement d’origine.
Si la configuration gérée impose sqlite_home, la base de données SQLite des journaux reste dans le répertoire requis, même si vous définissez log_dir. Consultez la configuration gérée.
Imposer le mode de journalisation à l’ensemble d’un parc
Arrêtez d’abord tous les clients sur chaque hôte qui utilise un répertoire personnel concerné. Le nom du paramètre contient unsafe, car la conversion d’une base de données pendant qu’un autre hôte y écrit risque de la corrompre.
Une fois les clients arrêtés, ajoutez le paramètre suivant à la configuration gérée des hôtes, dans /etc/codex/requirements.toml.
unsafe_enforce_sqlite_journal_mode = true
Ce paramètre s’applique à tous les utilisateurs des hôtes configurés. La prochaine fois qu’un utilisateur ouvrira Codex, celui-ci migrera automatiquement les bases de données WAL existantes à mesure qu’il les ouvrira en écriture sur NFS. Pour chaque répertoire personnel partagé, laissez la migration se terminer sur un hôte avant de reconnecter les autres hôtes. En cas d’échec, laissez les autres clients à l’arrêt et suivez les étapes de récupération.
Exécuter des traitements par lots indépendants
Si une tâche sans intervention humaine n’a pas besoin de l’historique de vos sessions interactives, exécutez codex exec avec un répertoire personnel Codex situé sur le disque local de la machine qui exécute la tâche. Si les fichiers de session doivent rester sur NFS, définissez CODEX_SQLITE_HOME sur un répertoire local privé propre à chaque tâche pour éviter que plusieurs machines se disputent l’accès à la même base de données.
- Conservez une trace de la conversation. Attribuez à chaque tâche un
CODEX_HOMEprivé et persistant pour son enregistrement de session et unCODEX_SQLITE_HOMEprivé sur le disque local de l’hôte pour sa base de données. Le processus qui exécute la tâche utilise un index distinct de celui de vos sessions interactives. Conservez l’enregistrement dans$CODEX_HOME/sessions/si vous devez examiner la tâche après la fin de ce processus. - Conservez uniquement le résultat. Placez le répertoire personnel de la tâche sur le disque local et exécutez
codex exec --ephemeral. Cette commande n’enregistre pas de session que vous pourriez reprendre. Utilisez-opour écrire la réponse finale dans un fichier persistant ou--jsonpour transmettre les événements en continu à votre outil d’exécution des tâches.
Si une tâche nécessite un enregistrement de session, configurez l’ordonnanceur pour qu’il crée les deux répertoires et fournisse au répertoire personnel de la tâche les éléments d’authentification et de configuration nécessaires. Remplacez les chemins de l’exemple par ceux du répertoire personnel Codex persistant de cette tâche et du répertoire SQLite local de la machine qui l’exécute. Une valeur de sqlite_home imposée par la configuration gérée ou définie dans la configuration est prioritaire sur CODEX_SQLITE_HOME.
CODEX_HOME="/mnt/nfs/codex/jobs/job-1234" \
CODEX_SQLITE_HOME="/var/local/codex/jobs/job-1234" \
codex exec "Résumez les étapes de compilation du projet contenu dans ce dépôt."
Questions fréquentes
Comment savoir si une erreur est liée à NFS ?
Une erreur de migration telle que cannot open source database exclusively indique que Codex n’a pas pu verrouiller la base de données. Un autre client peut aussi provoquer cette erreur sur un disque local. Sous Linux, exécutez findmnt -T "$DB_PATH" avec le chemin de la base de données concernée. Si la commande affiche nfs ou nfs4, recherchez sur chaque hôte les processus qui écrivent dans la base et demandez à l’administrateur du stockage de vérifier que le verrouillage fonctionne entre les hôtes sur ce montage. Arrêtez les clients encore actifs avant de réessayer.
Que faut-il vérifier dans la sortie de la commande de migration ?
Pour chaque base de données, Codex affiche Migrated database: et WAL backup:, ou bien Already in DELETE mode:. Si vous utilisez des permissions de groupe ou des règles d’accès étendues, vérifiez-les après la migration et avant de rouvrir les clients.
Si log_dir était déjà défini, la commande ignore la base de données des journaux. Avant de partager cette base entre plusieurs hôtes, vérifiez qu’elle utilise le mode DELETE ou conservez-la sur le disque local.
Si la commande affiche No databases found., vérifiez le répertoire SQLite effectivement utilisé pour le compte du propriétaire du répertoire personnel. Si l’espace local disponible pour les fichiers temporaires est insuffisant, choisissez sur l’hôte un répertoire local disposant de suffisamment d’espace et passez son chemin absolu avec --staging-dir.
Comment récupérer les données après l’échec d’une migration ?
Laissez les autres clients à l’arrêt. Notez le message d’erreur exact, le chemin de la base de données et le chemin de sauvegarde affiché. Il est possible que certaines bases de données aient déjà été migrées. Conservez la base de données d’origine et ses fichiers annexes ensemble dans leur répertoire de sauvegarde. Après avoir résolu un problème de verrouillage ou d’espace disque, relancez codex migrate-nfs-db sur le même hôte. En cas d’erreur d’intégrité ou de base de remplacement manquante, travaillez sur des copies avant toute restauration. Les enregistrements de session peuvent aider à reconstituer l’historique des conversations. Pour récupérer les données d’état stockées uniquement dans SQLite, notamment les objectifs, il faut disposer d’une base de données intacte.
Avant de lancer une session distincte de la CLI, vérifiez que les paramètres de stockage gérés ne redirigeront pas les écritures vers le répertoire personnel concerné. Démarrez ensuite Codex avec un répertoire temporaire sur le disque local. Vous devrez peut-être vous authentifier pour utiliser ce nouveau répertoire personnel.
recovery_home=$(mktemp -d /tmp/codex-nfs-recovery.XXXXXXXX) &&
CODEX_HOME="$recovery_home" CODEX_SQLITE_HOME="$recovery_home" \
codex --no-daemon --sandbox read-only \
"Aidez-moi à récupérer mes données après l’échec d’une migration de Codex sur NFS. Exécutez `$ codex doctor` pour obtenir des informations sur les bases de données corrompues. Le chemin de chaque sauvegarde devrait reprendre celui de la base de données d’origine, avec le suffixe `_wal_migration_backup` ajouté au nom du fichier. Demandez à l’utilisateur de vous fournir le message d’erreur d’origine. Proposez un plan de récupération qui utilise uniquement des copies. Laissez les fichiers d’origine intacts."