Fedora MacBook
Sleep fix for MBP 11,X
Fedora Linux on Apple MacBook might not be able to wake from sleep. (Or it might eventually wake up, but it can take several minutes.)
This package “apple_sleep”" is a workaround using “isolation” of CPUs, that allows the laptop to wake up from sleep within a normal timeframe.
I have no idea why it works, but I found the trick online - and polished the implementation as far as my Linux-fu allows. And it helps my Fedora-ized MacBook wake up from sleep.
There was some uncertainty about which cpu-num to isolate, so I made a script that isolates all but the first cpu; cpu0, and this seems to work … speedily.
The package consists of a Bash script and a systemd service file.
Usage
Put the files where you prefer, and edit the service file to point to the script. Enable the service, and sleep.target will trigger the service to source the script when the laptop goes to sleep, and again when it wakes up.
systemctl enable apple_sleep
apple_sleep.service
[Unit]
Description=Isolate cpu cores before sleep and restore after wake
Documentation=https://gist.github.com/jakob-hede/66e9f3439d0891f090fe99daef45cf0d
PartOf=sleep.target
[Service]
Type=simple
RemainAfterExit=yes
# Edit to customize script location:
Environment="APPLE_SLEEP_SCRIPT=/opt/optulation/mixed/apple_sleep/apple_sleep.sh"
ExecStart=/bin/bash -c '. ${APPLE_SLEEP_SCRIPT} START'
ExecStop=/bin/bash -c '. ${APPLE_SLEEP_SCRIPT} STOP'
[Install]
WantedBy=sleep.target
apple_sleep.sh
#!/bin/bash
# Documentation=https://gist.github.com/jakob-hede/66e9f3439d0891f090fe99daef45cf0d
# You must be root to run this script.
execute() {
debug() {
# Change to 'false' to disable debug output
true && printf "\e[35m%s\e[0m\n" "$*"
}
fail() {
printf "\e[31m%s\e[0m\n" "$*"
exit 1
}
is_apple() {
declare system_vendor txt
declare -i response
system_vendor=$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null)
if [[ "$system_vendor" == *Apple* ]]; then
response=0
txt="Running on Apple hardware"
else
response=1
txt="NOT running on Apple hardware"
fi
debug "${txt}"
return "${response}"
}
is_root() {
[[ $UID -eq 0 ]]
}
check_circumstances() {
is_root || fail "You must be root to run this script."
is_apple || fail "You must be running on Apple hardware to run this script."
}
argparse() {
indx=-99
if [[ $1 == 'START' ]]; then
indx=0
num=0
elif [[ $1 == 'STOP' ]]; then
indx=0
num=1
else
fail "Usage: $0 [START|STOP]"
fi
}
logify() {
declare log_file timestamp
timestamp=$(date +%H:%M:%S)
log_file="/tmp/${name}.log"
echo "${timestamp} ${*}. cpu_statuses: ${cpu_statuses}" >>"${log_file}"
debug "${name} ${timestamp} ${log_file} $* ${cpu_statuses}"
}
isolate() {
declare directory file
while ((indx > -1)); do
((indx++)) # We do not isolate CPU0, so we start at 1.
directory="/sys/devices/system/cpu/cpu${indx}"
[[ ! -d $directory ]] && indx=-99 && break
file="${directory}/online"
is_apple >/dev/null && echo "${num}" >"${file}"
cpu_statuses+="${indx}:$(cat ${file}) "
done
}
flow() (# <- subshell !!!
# Subshell ensures not to break some system stuff by doing 'exit'.
declare -i num indx
declare name cpu_statuses
name="$(basename "${BASH_SOURCE[0]%.*}")"
debug "${name} FLOW $*"
check_circumstances # Optionally disable while testing
argparse "$@"
# debug "solitude: ${num}"
isolate
logify "$@"
)
flow "$@"
}
execute "$@"
printf '\e[34mapple_sleep DONE %s\e[0m\n' "$?"