Home / Alt manpages / pkttyagent(1)

  • pkttyagent(1)
  • User command
  • linux

Run a TTY Authentication Agent with pkttyagent

A script needs polkit authorisation with no desktop session around to pop a graphical prompt. pkttyagent registers a text agent in your terminal instead. You will 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.

1. Check the installed command

Run these as your ordinary user. Starting an agent for your own session normally does not need sudo; elevated privileges can attach the agent to a different environment and make diagnosis harder, not easier.

$ command -v pkttyagent
/usr/bin/pkttyagent
$ pkttyagent --version
pkttyagent version 124
$ pkttyagent --help
Usage:
  pkttyagent [OPTION?]

The help output is the fastest way to confirm this installation supports --process, --system-bus-name, --notify-fd and --fallback. Remember the agent is a long-running helper, not a command that authenticates one request and exits.

Checkpoint

Continue only if command -v finds the executable and the version is the one you meant to use.

2. Choose the subject to serve

With no subject option, pkttyagent defaults to its parent process. That is convenient when another command launches the agent for you, but easy to misread when you start it yourself from a shell or wrapper. Use an explicit subject whenever the process or D-Bus owner actually matters.

For a process, pass a PID, or better, 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 actually intend to serve. The start-time format is operating-system dependent. The manual recommends the combined form because PIDs get recycled; supplying only a PID makes pkttyagent look up the start time itself, which can race with the process exiting and its PID being reused.

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 mistake a registration failure for an authentication failure: a misspelled or absent name is a subject-selection problem, nothing more.

3. Start the agent for a foreground test

Start it in the terminal where you want prompts to appear. --fallback tells polkit not to replace an existing agent, a cautious choice on a desktop or shared session where another agent might already be serving the same subject.

$ pkttyagent --fallback --process "$TARGET_PID,$TARGET_START_TIME"

If registration succeeds, the command sits there and only interacts with you when authentication is actually needed. Leave this terminal open while the operation that needs polkit runs somewhere else. An apparently idle process is normal when nothing is pending.

Do not hit Ctrl-C the moment you expect a password prompt. Let the requesting command finish or fail first, then stop the agent with Ctrl-C. There is no persistent configuration to undo here: registration simply ends when you kill this process.

Checkpoint

A successful registration means the process stays alive. A quick exit is not success; record the diagnostic and exit status before you start changing options.

4. Run a requesting operation and verify the boundary

From a second terminal, run the specific polkit action that needs authentication. Check that command's own documentation to identify it, and review its effect before you type a password. An agent only supplies a conversation channel: it grants no extra authorisation and it does not bypass polkit policy.

Keep the two terminal roles straight: the first owns the agent, the second owns the operation. If a prompt shows up in the wrong terminal, check which process or bus name the agent was actually registered for, and whether another agent is already active.

For a machine-readable registration signal, pass an open file descriptor with --notify-fd; the descriptor closes once the agent registers:

$ exec 9>"$TMPDIR/pkttyagent-ready"
$ pkttyagent --process "$TARGET_PID,$TARGET_START_TIME" --notify-fd 9

This is meant for a wrapper watching descriptor 9, not a notification file full of text. The shell redirection creates or truncates the named file, so pick a disposable path; never use a file you actually value merely as a descriptor target. A wrapper should close its descriptor and terminate the agent once the requesting operation finishes.

5. Diagnose a failed registration

The installed command uses distinct status codes worth memorising. Exit status 127 means the agent could not be registered, and the diagnostic goes to standard error. Exit status 126 means one or more options were malformed, and if standard input is a TTY, the manual page also gets 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 the command runs in, and whether an agent is already registered. Do not respond by piling on sudo: root access repairs neither a wrong PID nor a recycled process, a missing bus name, nor an unavailable polkit bus.

In scripts, preserve standard error and test the status immediately; a later command can overwrite $? and disconnect a useful diagnostic from its cause.

6. Stop and recover cleanly

Once 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 afterwards:

$ pkttyagent --fallback --process "$TARGET_PID,$TARGET_START_TIME" &
$ AGENT_PID=$!
$ printf 'agent pid: %s\n' "$AGENT_PID"
$ wait "$AGENT_PID"

That final wait blocks until the agent exits, so a real wrapper would run the requesting operation first and wait afterwards. If you need to cancel the workflow, send a normal termination signal to the saved agent PID, then confirm it has actually 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 an untrusted process list; confirm it is actually the agent you started. Stopping the agent does not roll back the protected operation itself, so check that operation's state separately if it got interrupted.

Done means

  • You confirmed the installed polkit and pkttyagent versions.
  • You selected an explicit process or D-Bus subject whenever the default parent process was not unambiguous.
  • You used --fallback wherever replacing an existing agent would be surprising.
  • You kept the agent terminal separate from the terminal running the protected operation.
  • You know status 126 means malformed options and 127 means registration failed.
  • You stopped the agent afterwards and confirmed no stray helper remains.