// post

2026-03-06 3 minutes macos

Control GlobalProtect from the macOS Terminal

A simple CLI script that lets you start, stop, restart, or completely kill GlobalProtect VPN on macOS using launchctl.

Control GlobalProtect from the macOS Terminal

Why This Exists

If you work in infrastructure, DevOps, or SRE, you’ve probably run into this: you need to quickly disconnect from VPN to test networking behavior, hit a public endpoint, debug DNS, or verify routing - but GlobalProtect requires digging through a GUI just to toggle the connection.

That’s friction.

  • test networking behavior
  • hit a public endpoint
  • debug DNS
  • access a local service
  • verify routing issues

But GlobalProtect requires digging through a GUI just to toggle the VPN.

That’s friction.

As system administrators, we prefer short commands that do one thing well.

Instead of remembering commands like this:

launchctl unload /Library/LaunchAgents/com.paloaltonetworks.gp.pangp*
launchctl load /Library/LaunchAgents/com.paloaltonetworks.gp.pangp*

…wrap it in a small utility:

gp stop
gp start
gp restart
gp toggle
gp kill

Fast. Predictable. Scriptable.

The Script

Create a new file:

/usr/local/bin/gp

Paste the following script:

#!/usr/bin/env bash
set -euo pipefail

SERVICE="com.paloaltonetworks.gp.pangp"
PLIST_GLOB="/Library/LaunchAgents/${SERVICE}*"
DOMAIN="gui/$(id -u)"

find_plists() {
  compgen -G "$PLIST_GLOB" || true
}

is_loaded() {
  launchctl print "${DOMAIN}/${SERVICE}" >/dev/null 2>&1
}

start_gp() {
  echo "Starting GlobalProtect..."
  for plist in $(find_plists); do
    sudo launchctl bootstrap "$DOMAIN" "$plist" 2>/dev/null || true
  done
}

stop_gp() {
  echo "Stopping GlobalProtect..."
  sudo launchctl bootout "${DOMAIN}/${SERVICE}" 2>/dev/null || true
}

kill_gp() {
  echo "Killing GlobalProtect completely..."

  stop_gp

  sudo pkill -9 -f PanGPS 2>/dev/null || true
  sudo pkill -9 -f PanGPA 2>/dev/null || true
  sudo pkill -9 -f pangps 2>/dev/null || true
  sudo pkill -9 -f GlobalProtect 2>/dev/null || true

  echo "GlobalProtect terminated."
}

restart_gp() {
  stop_gp
  sleep 2
  start_gp
}

status_gp() {
  launchctl list | grep -i palo || echo "No GlobalProtect services running."
}

toggle_gp() {
  if is_loaded; then
    stop_gp
  else
    start_gp
  fi
}

case "${1:-}" in
  start) start_gp ;;
  stop) stop_gp ;;
  restart) restart_gp ;;
  toggle) toggle_gp ;;
  kill) kill_gp ;;
  status) status_gp ;;
  *)
    echo "Usage: gp {start|stop|restart|toggle|kill|status}"
    ;;
esac

Install the CLI

Make the script executable and verify it’s on your PATH:

sudo chmod +x /usr/local/bin/gp
which gp
# /usr/local/bin/gp

Usage

CommandDescription
gp startStart the VPN
gp stopStop the VPN
gp restartStop then start
gp toggleStart if stopped, stop if running
gp statusList running GlobalProtect services
gp killForce-kill all processes

gp kill

gp kill

The kill command goes further than stop - it unloads all launch agents, force-kills running processes, and prevents automatic restart. Most useful when debugging networking or routing issues where the VPN interferes even after a normal stop.

How It Works

GlobalProtect installs launch agents under /Library/LaunchAgents. The relevant services are:

com.paloaltonetworks.gp.pangp
com.paloaltonetworks.gp.pangpa

macOS manages these via launchctl, the system service manager. By booting services out of the user launch domain (gui/<uid>), we can programmatically disable the VPN without touching the GUI.

Quick Toggle Alias

Add this to your .zshrc or .bashrc:

alias vpn="gp toggle"

Now toggle the VPN with a single word:

vpn

Final Thoughts

Good system administration often comes down to removing friction.

Small scripts. Short commands. Repeatable workflows.

Instead of digging through a GUI every time you need to toggle VPN access, you now have a simple CLI tool that does it instantly.