Run a TTY Authentication Agent with pkttyagent
You will register a polkit text authentication agent in your terminal, attach it to the right subject, and stop it cleanly when the operation is over. Allow about ten minutes for a first test. This guide describes the pkttyagent supplied by polkit 124 in Ubuntu's polkitd 124-2ubuntu1.24.04.4 package, so check your installed version before relying on details in a script.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Check the installed command
Run these commands as your ordinary user. Starting an agent for your own session normally does not require sudo; using elevated privileges can attach the agent to a different environment and make diagnosis harder.
$ command -v pkttyagent
/usr/bin/pkttyagent
$ pkttyagent --version
pkttyagent version 124
$ pkttyagent --help
Usage:
pkttyagent [OPTION?]
The help output is the quickest way to confirm that this installation supports --process, --system-bus-name, --notify-fd and --fallback. The agent is a long-running helper, not a command that authenticates one request and then exits.
Checkpoint
Continue only if command -v finds the executable and the version is the one you intend to use.
2. Choose the subject to serve
With no subject option, pkttyagent uses its parent process. That default is convenient when another command launches the agent, but it is easy to misunderstand when the agent is started from a shell or wrapper. Use an explicit subject when the process or D-Bus owner matters.
For a process, pass a PID, or preferably a PID together with its start time:
$ ps -o pid=,lstart= -p "$TARGET_PID"
$ pkttyagent --process "$TARGET_PID,$TARGET_START_TIME"
Replace both placeholders with values from the process you intend to serve. The exact start-time format is operating-system dependent. The manual recommends the combined form because PIDs can be recycled. Supplying only a PID makes pkttyagent look up the start time itself, but that lookup can race with process exit and PID reuse.
For a D-Bus subject, pass the well-known or unique bus name that owns the operation:
$ pkttyagent --system-bus-name org.example.Service
Use a real bus name from your application or service. Do not invent one and treat a registration failure as an authentication failure: a misspelled or absent name is a subject-selection problem.
3. Start the agent for a foreground test
Start it in the terminal where you want to see prompts. --fallback tells polkit not to replace an existing agent. This is a cautious choice on a desktop or shared session, where another agent may already be serving the same subject.
$ pkttyagent --fallback --process "$TARGET_PID,$TARGET_START_TIME"
If registration succeeds, the command remains running and interacts with you only when authentication is needed. Leave this terminal open while the operation that needs polkit runs in another terminal. When no request is pending, an apparently idle process is normal.
Do not press Ctrl-C immediately if a password prompt is expected. First let the requesting command finish or fail, then stop the agent with Ctrl-C. There is no persistent configuration change to undo: the registration ends when this process is killed.
Checkpoint
A successful registration means the process stays alive. A quick exit is not success; record the diagnostic and its exit status before changing options.
4. Run a requesting operation and verify the boundary
From a second terminal, run the specific polkit action that needs authentication. Use the command's own documentation to identify it and review its effect before entering a password. An agent supplies a conversation channel; it does not grant extra authorisation and it does not bypass polkit policy.
Keep the two terminal roles clear: the first terminal owns the agent, and the second owns the operation. If the operation prompts in the wrong terminal, check which process or bus name the agent was registered for and whether another agent is already active.
If you need a machine-readable registration signal, pass an open file descriptor with --notify-fd. The descriptor is closed after the agent registers:
$ exec 9>"$TMPDIR/pkttyagent-ready"
$ pkttyagent --process "$TARGET_PID,$TARGET_START_TIME" --notify-fd 9
This example is intended for a wrapper that watches descriptor 9. It is not a notification file containing text. The shell redirection creates or truncates the named file, so choose a disposable path and do not use a valuable file merely as a descriptor target. A wrapper should close its descriptor and terminate the agent after the requesting operation finishes.
5. Diagnose a failed registration
The installed command uses distinct status codes. Exit status 127 means the authentication agent could not be registered, and the diagnostic is written to standard error. Exit status 126 means one or more options were malformed. When standard input is a TTY, the manual page is also shown for malformed options.
$ pkttyagent --process nope
pkttyagent: Invalid process specifier `nope'
$ printf 'exit status: %s\n' "$?"
exit status: 126
For a 127 failure, check the subject, the D-Bus session or system environment in which the command runs, and whether an agent is already registered. Do not respond by repeatedly adding sudo. Root access cannot repair a wrong PID, a recycled process, a missing bus name or an unavailable polkit bus.
For scripts, preserve standard error and test the status immediately. A later command can overwrite $?, making a useful registration diagnostic difficult to connect to its cause.
6. Stop and recover cleanly
When the protected operation has ended, return to the terminal running pkttyagent and press Ctrl-C. If a wrapper started it in the background, save its PID and terminate that process after the operation:
$ pkttyagent --fallback --process "$TARGET_PID,$TARGET_START_TIME" &
$ AGENT_PID=$!
$ printf 'agent pid: %s\n' "$AGENT_PID"
$ wait "$AGENT_PID"
The final wait blocks until the agent exits, so a real wrapper would run the requesting operation before waiting. If you cancel the workflow, send a normal termination signal to the saved agent PID and then check that it has gone:
$ kill "$AGENT_PID"
$ wait "$AGENT_PID" 2>/dev/null || true
$ kill -0 "$AGENT_PID" 2>/dev/null && echo 'still running' || echo 'agent stopped'
Do not kill a PID copied from an old terminal or from an untrusted process list. Confirm that it is the agent you started. Stopping the agent does not roll back the protected operation itself, so inspect the operation's state separately if it was interrupted.
Done means
- You confirmed the installed polkit and
pkttyagentversions. - You selected an explicit process or D-Bus subject when the default parent process was not unambiguous.
- You used
--fallbackwhere replacing an existing agent would be surprising. - You kept the agent terminal separate from the terminal running the protected operation.
- You know that status 126 means malformed options and 127 means registration failed.
- You stopped the agent after the operation and confirmed that no stray helper remains.