Run session-migration safely and debug user-session scripts
You will learn how Ubuntu's session-migration command finds migration scripts, how to preview the work, and how to run one script explicitly when debugging a user session. The examples target the installed session-migration package version 0.3.9build1. Allow about ten minutes. You need a shell and access to the user session whose files or settings are being migrated.
The route
Jump straight to the step you need, or tick off Done means at the end.
This tool is normally started automatically near the beginning of a graphical session. It runs executable files supplied in a session-migration scripts directory, in ASCII order, and remembers migrations so they are not normally repeated. Treat every script as a state-changing program even when the wrapper itself looks harmless.
1. Confirm the installed command
Start with an ordinary, unprivileged check:
$ command -v session-migration
/usr/bin/session-migration
$ dpkg-query -W -f='${Package} ${Version}\n' session-migration
session-migration 0.3.9build1
The package installs a user systemd service which runs /usr/bin/session-migration before graphical-session-pre.target. You normally do not need sudo, and running the command as root can make a migration operate on the wrong home directory or session environment.
Checkpoint: if command -v finds nothing, stop here. Install or repair the package using your normal system administration process rather than copying a binary from another machine.
2. Preview the normal script search
Use --dry-run with --verbose before allowing migrations to run:
$ session-migration --dry-run --verbose
Directory '/usr/local/share/session-migration/scripts' does not exist, nothing to do
Using '/usr/share/session-migration/scripts' directory
Executing: /usr/share/session-migration/scripts/dark-theme-migration.sh
Executing: /usr/share/session-migration/scripts/nautilus_thumbnail_cache_clear.sh
Directory '/var/lib/snapd/desktop/session-migration/scripts' does not exist, nothing to do
The exact directories depend on XDG_DATA_DIRS in the session. Each data directory is checked for session-migration/scripts. Missing directories are reported and skipped. Existing executable files are listed in ASCII order. The command returned status 0 in this test.
--dry-run prevents the scripts being launched and prevents them being marked as migrated. The verbose line says Executing because it describes the candidate action; it is not proof that the script ran. Check the status immediately when scripting:
session-migration --dry-run --verbose
status=$?
printf 'session-migration status: %s\n' "$status"
exit "$status"
3. Inspect scripts before removing the safety net
Migration scripts are ordinary executable files. Read the relevant files and check their permissions before changing anything:
$ find /usr/share/session-migration/scripts -maxdepth 1 -type f -perm /111 -printf '%f\n' | sort
$ sed -n '1,160p' /path/to/session-migration/scripts/example.sh
Do not assume that a script is idempotent. The manual says scripts should be safe to run more than once because the wrapper's timestamp cache is not a substitute for idempotence. A script might alter a desktop setting, move a configuration file, clear a cache or contact another user-session service.
There is no rollback command in session-migration. Before a migration changes a configuration file, make a backup using the file's normal format. For a setting changed through a desktop configuration service, record its current value and use that service's documented command to restore it. Keep the original until the session has been checked.
4. Test one script with --file
To investigate one script, pass its path to --file and keep the dry-run flag:
$ session-migration --dry-run --verbose \
--file /path/to/session-migration/scripts/example.sh
Executing: /path/to/session-migration/scripts/example.sh
--file ignores the normal XDG script directories and considers only the named file. It also does not record that file as migrated. Use an absolute path while debugging so a changed working directory cannot select a different file. The file still needs to be executable for normal migration use.
Only remove --dry-run after reading the script and confirming its backup or recovery path. Run the command as the session user:
$ session-migration --verbose \
--file /path/to/session-migration/scripts/example.sh
Executing: /path/to/session-migration/scripts/example.sh
$ printf 'status=%s\n' "$?"
status=0
The wrapper's status reports whether its processing completed; it does not prove that a migration produced the intended desktop state. Verify the changed file or setting with the relevant read-only command afterwards.
5. Diagnose the common traps
If a script is listed but appears not to run on the next session, check whether it has already been recorded as migrated. Do not delete migration state blindly: that can make every previously run migration eligible again. First inspect the package's current data and the script's own logs, then make a backup before any state reset.
If no scripts appear, compare the session's environment with an interactive shell:
$ printf 'XDG_DATA_DIRS=%s\n' "${XDG_DATA_DIRS-}"
$ find /usr/local/share /usr/share -path '*/session-migration/scripts' -type d -print 2>/dev/null
A shell started outside the graphical session may have different XDG variables. Test from the affected session before concluding that a package or script is missing. If one script fails, run it separately only when its contents and side effects are understood. Do not use sudo to paper over a permission error without checking which user owns the session data.
Done means
- The installed command and package version are known.
- A verbose dry run shows the directories and scripts selected for the session.
- Each relevant script has been inspected for side effects and repeat safety.
--fileand an absolute path are used for focused debugging.- Any real migration has a recorded backup, a verification step and a recovery path.