I am not a big fan of using Bluetooth for connecting to peripherals. They inevitably stop working at some point and you’re left without a working keyboard or mouse or both.

Recently I suspended my scepticism and purchased the Logitech Lift for Mac. I was getting some RSI and wanted to try out this vertical mouse.

Logitech Lift for Mac

Logitech Lift for Mac

The mouse is exceptional. It was working really well, until one day, as expected, the mouse could not be detected by macOS (Monterey).

Curse your sudden but inevitable betrayal!

Since I knew this day would come, I had a handy wired USB mouse close by. Surprisingly even after disabling and enabling Bluetooth the mouse would not pair on its previous channel.

I changed channels and finally got the mouse to pair. This was quite annoying as now I had two channels bound to the same computer. I did some Googling and found that killing the Bluetooth daemon seemed to solve the problem. Once the daemon is killed, a new instance is automatically started.

Script it

I created a small Bash script to do that. In order to use the script I had use gnu-sed as opposed to the default sed implementation that ships with macOS, because I wanted to do some Regex replacements.

You can install it via brew:

brew install gnu-sed

If you want to make gnu-sed your default sed, then you can just add it to your path as mentioned in this article.

The kill script: kill-bluetooth.sh is as follows:

#!/bin/bash

PROC_ID=$(ps aux | grep 'bluetoothd' | grep -v 'grep' | /usr/local/opt/gnu-sed/libexec/gnubin/sed -E 's/\s+/ /g' | cut -d' ' -f2)

echo "bluetoothd Proc Id: $PROC_ID"

sudo kill -9 "$PROC_ID"

These are the steps followed in the script:

  1. Find any processes named “bluetoothd” (ps aux | grep 'bluetoothd')
  2. Unfortunately this also returns the grep we ran above. Exclude it. (grep -v 'grep')
  3. Any time we have more than a single space, replace it with a single space (sed -E 's/\s+/ /g')
  4. Split the output by spaces and get the second field which is the process id(cut -d' ' -f2)
  5. Assign the process id to PROC_ID
  6. Write out PROC_ID to the terminal (echo "bluetoothd Proc Id: $PROC_ID")
  7. Kill the process with the process id of PROC_ID (sudo kill -9 "$PROC_ID")

I’ve explicitly specified the path to the gnu-sed implementation because I want to run this script through Alfred. More on that later.

Running the above script fixes the problem when Bluetooth fails to detect my mouse!

Hooray

Hooray

Make Alfred do it

But what if we could make it even easier? And we can, by running it through an Alfred Workflow script.

One thing we will need is to give the script administrative privileges in order to run the sudo command. We can do this by wrapping it in an AppleScript:

do shell script "/bin/bash PATH_TO_SCRIPT/kill-bluetooth.sh" with administrator privileges
Alfred Workflow Script

Alfred Workflow Script

This will now prompt you for the administrator password when running the script.

And now you can simply define a keyword to such as “Relaunch Bluetooth” to launch your Alfred Workflow and restart your bluetoothd daemon.

Alfred Workflow

Alfred Workflow

Relaunch Bluetooth

Relaunch Bluetooth