How To Install macOS Virtual Machine on Linux/Arch/Manjaro – Catalina, Mojave, or High Sierra! XCode working! Tutorial for Ubuntu/RHEL/CentOS/Fedora

Linux users on Arch or Manjaro attempting to install macOS/OSX in VMWARE, or QEMU/KVM, will greatly benefit from this tutorial.

UPDATED 25 May 2020.
Currently there is an OpenCore boot solution, which is far superior for Arch users. I have added it to the tutorial.

UPCOMING: Dockerfile full auto macOS installer. Will be released May 28th 2020.

This tutorial now covers:
MacOS VM on Arch, Ubuntu, Debian, CentOS, RHEL or Fedora.

Check if your CPU has virtualization. This out of the following command must be greater than 0.
It tells you how many cores can be used in virtualization. You might see 8, 12, 64.

# ALL DISTROS
egrep -c '(svm|vmx)' /proc/cpuinfo

If you see 0 when you ran the above command, then boot into your BIOS and turn on “Hardware Virtualization.”
If you see 1, 2, 3 … any number greater than 0 then you can ready!

This tutorial is great for Linux users who want to use XCode 10 or 11 on Linux without Dual Booting!

How to Install macOS VM on Linux

Linux System Requirements:

  • about 20-40gb of free space
  • Intel VT-x / AMD SVM: in your BIOS turn on “hardware virtualization” or similar

Suggestions:

  • highly recommend using an SSD
  • where you download and run the scripts will determine which drive the OSX image will be created on

ARCH ONLY: an aur package manager, such as yay.

If you don’t have yay (Arch User Repository package manager):

# ARCH LINUX USERS ONLY
pacman -S git make automake gcc python go autoconf cmake pkgconf alsa-utils fakeroot --noconfirm
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si

Next, we will need git & python as we will need to clone some repositories.

# ARCH LINUX
sudo pacman -S git python

# UBUNTU DEBIAN
sudo apt install git python

# CENTOS RHEL FEDORA
sudo yum update -y
sudo yum install epel-release
sudo yum install git python -y

We are going to download the official the MAC iso/dmg file, which is around 6GB downloaded.
Make sure you download the iso in the disk or device that you are going to run the VM from.
A great way to download OSX ISO files is using gibMacOS:

git clone https://github.com/corpnewt/gibMacOS.git
cd gibMacOS
chmod +x gibMacOS.command
./gibMacOS.command

# if this doesn't work
python gibMacOS.command
python2.7 gibMacOS.command
python2 gibMacOS.command

This will run a small Python script that will allow you to download the official Mac iso files from *.apple.com

The version that I run is Mojave 10.14.6.

macOS Mojave 10.14.6 (18G103)

gibmacos Choose macOS ISO for Downloading on Linux
gibmacos Choose macOS ISO for Downloading on Linux

Next, you will need qemu & libvirt for virtualisation and emulation.
Also required during qemu installation:
dnsmasq for networking
virt-manager but not required
bridge-utils for additional networking Requirements

# ARCH LINUX ONLY
sudo pacman -S qemu libvirt dnsmasq virt-manager bridge-utils flex bison ebtables edk2-ovmf

# UBUNTU DEBIAN
sudo apt install qemu qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virt-manager
sudo apt install qemu virt-manager dnsmasq  bridge-utils

# CENTOS RHEL FEDORA
sudo yum install libvirt qemu-kvm -y

Now, enable libvirt and virtlogd

  • libvirt is libraries required for virtualisation
  • virtlogd is logging of the qemu virtual instances
sudo systemctl enable libvirtd.service
sudo systemctl enable virtlogd.service

Additionally, you will require the following packages which are found only in the Arch User Repository.

Most of them are on Github if you want to compile them yourselves.
Installing these will take some time, so one-by-one install these:

# ARCH LINUX ONLY
# you may need the following
yay uml_utilities # read below if doesn't install
yay libguestfs # libguestfs is in arch/comminuty-testing now too
yay ebtables
yay firewalld
sudo firewalld

Update May 2020: ARCH uml_utilities may need to be installed in the following way:

# ARCH ONLY
# the current version of uml_utilities may need to be installed in the following way
# because the pkgbuild has a tiny error, if it gets fixed, this snippet will still work fine with r
yay --getpkgbuild uml_utilities
cd uml_utilities
perl -i -p -e "s/provides=\(\'\'\)/provides=\(\)/g" PKGBUILD
perl -i -p -e "s/conflicts=\(\'\'\)/conflicts=\(\)/g" PKGBUILD
makepkg -si

If you are on Debian or Ubuntu

# DEBIAN UBUNTU
sudo apt install qemu qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virt-manager uml-utilities dmg2img wget libguestfs-tools

The following program qt-virt-manager is huge and takes a long time to compile but you might need it:

# yay qt-virt-manager

You should reboot now to apply kernel changes for qemu.

sudo modprobe kvm
reboot

After reboot, download the OSX-KVM Repository:
This folder will be referred to as the OSX-KVM folder.

Your macOS disk will be created in the folder we are about to download into.

Make sure you choose a disk with enough space.

git clone https://github.com/kholia/OSX-KVM.git
cd OSX-KVM
# if you didnt use gibMacOS to download the OSX ISO you can use: 
# ./fetch-macOS.py

Converting macOS BaseSystem.dmg into Disk Image

In the gibMacOS folder that you downloaded earlier, navigate into:
macOS Downloads > publicrelease, and then the folder of the OSX Version that you downloaded.

Inside the macOS version folder that you downloaded from gibMacOS, we will turn the .dmg into .img
Make sure you have enough disk space here!

Find BaseSystem.dmg inside the gibMacOS downloaded folder. It should be around 500mb.
Convert it to .img:

# do this inside gibMacOS/macOS Downloads/publicrelease/061-26589 - 10.14.6 macOS Mojave/
qemu-img convert BaseSystem.dmg -O raw BaseSystem.img

# or do it inside any version auto
qemu-img convert gibMacOS/macOS\ Downloads/publicrelease/*/BaseSystem.dmg -O raw BaseSystem.img

Now move the BaseSystem.img that you just created FROM the gibMacOS folder -> TO THE OSX-KVM FOLDER

Move BaseSystem to OSX-KVM Folder
Move BaseSystem to OSX-KVM Folder

Decide now how big you want the macOS disk size to be.

I want an 80GB macOS disk size so I run the command below.
Note: do not change “mac_hdd_ng.img” or it will break the scripts later.

qemu-img create -f qcow2 mac_hdd_ng.img 80G

The 80GB empty disk has been created.
The macOS image is ready.

Now, create the network for the OSX VM

If you have successfully installed all the AUR packages above, you should be able to run this:

Run these commands one-by-one:

sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up promisc on
sleep 1
sudo virsh net-start default
sudo virsh net-autostart default
sudo ip link set dev virbr0 up
sleep 1
sudo ip link set dev tap0 master virbr0
macOS VMWARE Virtual Networking
macOS VMWARE Virtual Networking

Mac is now ready to boot.

Inside the OSX-KVM folder, run the shell script run-diagnostics.sh

./run-diagnostics.sh

If everything looks okay, you are ready to boot macOS on Arch Linux.
If everything is not okay, leave a comment, I usualy reply within 24 hours. use imgur.com to link to image if you want to post a screenshot

macOS Run Diagnostics
macOS Run Diagnostics

Boot macOS

# new shell boot script version! As of May 2020
./OpenCore-Boot.sh
# old tutorial, may fail
./boot-macOS-NG.sh

Boot and Installation Process

Hint: in QEMU, press Ctrl + Alt + G to gain control of your mouse again.

At the CLOVER Boot Manager screen, select:
Boot macOS Install from macOS Base System

macOS Clover Boot Linux AMD OSX
macOS Clover Boot Linux AMD OSX

After about a minute, the macOS recovery GUI will appear and you can select your language.

When you reach the macOS Utilities screen, seleck “Disk Utility”

macOS on Linux Disk Utility
macOS on Linux Disk Utility

In the top left, select “Show All Devices”. Not required to see the disk we are using, but helpful to visualize what is happening

Show All Devices OSX Disk Utility
Show All Devices OSX Disk Utility

Select the disk which has 80GB and is “Uninitialized”.

Uninitialized QEMU Disk for macOS on Linux
Uninitialized QEMU Disk for macOS on Linux

Click on “Erase” and erase the 90GB disk.

Do not change the Format or Scheme.

Erasing the disk here does nothing to your real computer. This is a virtual drive.

Erase Disk macOS Linux
Erase Disk macOS Linux

Create a new partition for macOS on your QEMU Drive

NOTE: YOU MUST REDUCE THE DISK SIZE BY A SMALL AMOUNT TO BE ABLE TO PRESS APPLY

After you have erased the disk, click “Partition”.

Partitioning QEMU Drive on Linux for macOS
Partitioning QEMU Drive on Linux for macOS
Change 85.6 to 85.5 and you will be able to press apply.
You Must Reduce the Partition Size by any amount
You Must Reduce the Partition Size by any amount.

Note: this will NOT steal 80GB straight away from your hard drive:  it’s just virtually allocating it from your host machine’s disk.

Create macOS partition for Arch Linux QEMU
Create macOS partition for Arch Linux QEMU

When that has finished, you can close the “Disk Utility”

Select Reinstall macOS.

Reinstall macOS on QEMU
Reinstall macOS on QEMU
Install macOS Mojave on Arch Linux
Install macOS Mojave on Arch Linux

Have fun using macOS on Linux with QEMU!

Install XCode on Arch Linux
Install XCode on Arch Linux

Finsihed installing OSX on Linux in a VM!

 

BONUS DESKTOP SHORTCUT SCRIPT!

# boot macosx  vm
sudo systemctl enable libvirtd.service
sudo systemctl enable virtlogd.service
sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up promisc on 
sleep 1
sudo virsh net-start default
sudo virsh net-autostart default
sudo ip link set dev virbr0 up
sleep 1
sudo ip link set dev tap0 master virbr0

cd /home/user/OSX/OSX-KVM/ && bash ./OpenCore-Boot.sh

 

Update May 2020 fixes for existing Mac OSX Virtual Machines:

virsh is now included in libvirtd.

Something happened to my tun setup but I documented the fix in this article about TUN/TAP OSX-KVM

You may need to remove the git version of virsh that we are using and use the one from libvirtd:

# remove the existing networks created by the old package
# dont worry, these will get created again when you reinstall qemu and libvirt
# 
sudo pacman -R virsh
sudo ip link delete virbr0
sudo ip link delete virbr0-nic
sudo pacman -S libvirt qemu
reboot

It seems we don’t need this command any more because the libvirt package includes virsh.
Remove any virsh commands from your boot scripts (the bonus one above).

# I removed these
# sudo virsh net-create default
# sudo virsh net-autostart default

qemu-system-x86_64: could not configure /dev/net/tun (tap0): Operation not permitted

Or

command “sudo virsh net-start default” hangs

This error happened when I updated the kernel.

Solved by reinstalling qemu and libvirt:

sudo pacman -R virsh
sudo ip link delete virbr0
sudo ip link delete virbr0-nic
sudo pacman -S libvirt qemu
reboot

Then change the networking mode to Usermode. You can do that by importing the whole thing into virt-manager by using the file named macOS-libvirt-Catalina.xml. Happy to help with any questions you might have!

Increase Screen Resolution on MacOS Virtual Machine QEMU!

– Automatically fixed in the new OpenCore-Boot.sh version
– Try the new OpenCore-Boot version.

How To Setup VNC, XRDP, XDoTool on Ubuntu (Azure, Gcloud)

How To Setup VNC, XRDP, XDoTool on Ubuntu (Azure, Gcloud)

# update
sudo apt update -y

# install xdotool
sudo apt install xdotool -y

# prepare xfce desktop env
sudo apt install xfce4 xfce4-goodies -y

# vnc4server causes segmentation fault with xdotool so we will be using xrdp + vnc
sudo apt install vnc4server xrdp -y

# enable xrdp
sudo systemctl enable xrdp

# add ssl user
sudo adduser xrdp ssl-cert

# add startxfce4 to the startup
echo ""exec startxfce4"" | sudo tee -a /etc/xrdp/xrdp.ini

# restart xrdp
sudo systemctl restart xrdp

# if you are using REMMINA and your remote desktop server is xrdp you need to check
# "Relax Order Checks" on the Advanced Tab in the profile

# disable extra security
sudo apt install selinux-utils -y
setenforce 0

# start a big screen session
vncserver -geometry 1920x1080

# and kill it
vncserver -kill :1

# reload daemons
sudo systemctl daemon-reload

# enable vncserver
sudo systemctl enable --now [email protected]

# open the xrdp port and the vnc port
sudo ufw allow 5901
sudo ufw allow 3389

# if you are using RHEL/CENTOS
# sudo firewall-cmd --permanent –add-port=5901/tcp
# sudo firewall-cmd --permanent –add-port=3389/tcp
# sudo firewall-cmd –reload

# open some applicationsa
export DISPLAY=:1
xfwm4 &
xfce4-panel &
xdotool getmouselocation

Install XFCE CentOS 8

As CentOS is new, we need to add additional repos, namely epel-testing.

First, install yum utils to get yum-config-manager

yum install yum-utils -y
dnf install yum-utils -y

Then, enable EPEL testing which has all the missing packages from CentOS 7 in CentOS 8.

yum install epel-release -y
yum-config-manager --enable epel-testing

Bare minimum desktop:

yum install xfce4-panel Thunar xfce4-appfinder xfdesktop -y

All the extras:

dnf --enablerepo=epel-testing install xfce4-panel Thunar thunar-volman tumbler tumbler-extras \
xfce4-appfinder xfce4-power-manager xfce4-settings \
xfdesktop xfce4-session  xfce4-terminal  \
xfce4-notifyd

 

Install Python 3.8 on CentOS 7 or 8

Here is a one block automated install for Python3.8 on CentOS:

yum install make gcc openssl-devel bzip2-devel libffi-devel -y
cd /opt
wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz
tar xzf Python-3.8.0.tgz
cd Python-3.8.0
./configure --enable-optimizations
make altinstall
rm Python-3.8.0.tgz
python3.8 --version
cd /root

Selenium Stopped Working 2019 Python Selenium Geckodriver Sock Error: Cannot Connect/Create Connection to Browser

I recently upgraded Firefox to the latest build.

Then, my geckodriver binary stopped working in Python.

firefox --version
Mozilla Firefox 71.0

python --version
Python 3.8.0

/bin/geckodriver --version
geckodriver 0.24.0

The main problem, I had an outdated Geckodriver version (from the distro repo)

sudo pacman -R geckodriver
/bin/geckodriver --version
bash: /bin/geckodriver: No such file or directory

Find the latest version

https://github.com/mozilla/geckodriver/releases/

cd /opt
sudo wget https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz

sudo tar -xzvf geckodriver.tar.gz && rm -f geckodriver.tar.gz

sudo chmod +x geckodriver

sudo chmod 755 geckodriver

sudo cp geckodriver /bin/geckodriver

Geckordriver should be updated to the latest version:

geckodriver --version
geckodriver 0.26.0

OneLiner: Upgrade All PIP and PIP3 Python Packages to Latest Version

“pip3 list –outdated” shows us all installed packages that are currently out of date.

pip3 list --outdated

Sample Output

Package
------------------
certifi
h11
httpcore
importlib-metadata
lit
...

xargs –update, excluding the “Packages” and “——…” header lines

sudo pip3 list --outdated | \
awk -F" " '{ print $1 }' | \
grep -v "Package\|------------------" | \
xargs sudo pip3 install --upgrade

And as a one-liner:

sudo pip3 list --outdated | awk -F" " '{ print $1 }' | grep -v "Package\|------------------" | xargs sudo pip3 install --upgrade
Auto Upgrade Python PIP Modules Libraries
Auto Upgrade Python PIP Modules Libraries

Install Docker on CentOS 8 – Automatically!

Docker doesn’t come with “stock” repos on CentOS, some variations of alias programs are installations like podman.

These lack many of the core commands of the “real” Docker.

Here is a guide to install Docker Latest Version on CentOS.

yum clean all -y
yum update -y
yum upgrade -y

dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo

DOCKERVERSION=$(dnf list docker-ce --showduplicates | \
sort -r | \
grep "docker-ce.x86_64" -m1 | \
sed -e 's/docker\-ce\.x86\_64//g' -e 's/docker\-ce\-stable//g' | \
tr -d [:space:])

# if the above fails, try the latest compatible via
dnf install docker-ce-$DOCKERVERSION -y

Generate Random Numbers on Bash or Shell Using Builtins $random

As we all know, the shell builtin variable $RANDOM is a pseudo random number generator.

Today, we will be looking at some creative ways to generate psuedo random numbers, trying to use shell builtins as much as possible.

The Best Solution is shuf (not exactly builtin though)

# Shuffle and return n'th line of range
shuf --head-count="1" --input-range="1-10000"
shuf -n1 -i1-10000
9523

Ways to generate various strings of numbers in BASH

# Generate a number between 0 - 32767
echo $RANDOM
7469

$RANDOM Caveats

From the 2 above scenarios, we analyse the distribution of the digits and find out the frequency of each value in order to see how random they really are:

# Count the frequency of numbers in a 10000 samples
# cut -c1 chops the first digit from our variable

for i in $(seq 1 1000); do
    RNUMS+=($(cut -c1 <<< $RANDOM))
done

### OR

while [[ $COUNTER -le 1000 ]]; do
     RNUMS+=($(cut -c1 <<< $RANDOM))
     COUNTER=$COUNTER+1
done

# show RNUMS array length, should be 1000
echo ${#RNUMS[@]}

Now, we want to test the frequency of each digit:

for n in ${RNUMS[@]}; do
    case $n in
        1 ) ((ones++))
            ;;
        2 ) ((twos++))
            ;;
        3 ) ((three++))
            ;;
        4 ) ((fours++))
            ;;
        5 ) ((fives++))
            ;;
        6 ) ((sixes++))
            ;;
        7 ) ((sevens++))
            ;;
        8 ) ((eights++))
            ;;
        9 ) ((nines++))
            ;;
        0 ) ((zeros++))
            ;;
    esac
done

echo $ones $twos $threes $fours $fives $sixes $sevens $eights $nines $zeros

Strangely, the output expected should be ~100, ~100, ~100…

However, the output is totally different:

330 367 108 22 41 28 30 42 33

Creative Ways To Generate Bad Random Numbers In Bash

The second digit from $RANDOM$RANDOM

cut -c2 <<< $RANDOM$RANDOM

# cut the 2nd digit from RANDOMRANDOM
# $RANDOM's minimum value is 1 therefore the second digit should always be there
# Do not use this value on its own though, as it clearly is not random
while [[ $COUNTER -le 1000 ]]; do
     RNUMS+=($(cut -c2 <<< $RANDOM$RANDOM))
     COUNTER=$COUNTER+1
done
# frequency test
111 114 92 97 86 87 89 95 105 125

# again
120 100 108 93 100 97 78 83 97 125

# CLEARLY NOT RANDOM

A digit from $(date +%N)

cut -c9 <<< $(date +%N)

# Print the time in nanoseconds of the current moment
# Do not use this value on its own though, as it clearly is not random
date +%N
277936336
while [[ $COUNTER -le 1000 ]]; do
     RNUMS+=($(cut -c9 <<< $(date +%N)))
     COUNTER=$COUNTER+1
done
# frequency test
103 89 105 92 102 104 100 106 91 109
# DECENTLY RANDOM

A digit from cksum <<< $RANDOM$RANDOM

cut -c2 <<< $(cksum <<< $RANDOM$RANDOM)

# Checksum $RANDOM$RANDOM
echo $(cksum <<< $RANDOM$RANDOM)
277936336
while [[ $COUNTER -le 1000 ]]; do
     RNUMS+=($(cut -c2 <<< $(cksum <<< $RANDOM$RANDOM)))
     COUNTER=$COUNTER+1
done
# frequency test
128 123 91 78 101 95 85 86 92 122
# again
124 111 110 79 82 91 100 103 84 117
# and again
126 118 104 92 101 85 88 87 86 114
# CLEARLY NOT RANDOM!

A digit from cksum <<< $(($RANDOM*$RANDOM))

cut -c2 <<< $(cksum <<< $(($RANDOM*$RANDOM)))

# Checksum $RANDOM x $RANDOM
while [[ $COUNTER -le 1000 ]]; do
     RNUMS+=($(cut -c2 <<< $(cksum <<< $(($RANDOM*$RANDOM)))))
     COUNTER=$COUNTER+1
done
# and analysis
112 127 107 103 88 84 106 85 81 108
126 106 97 99 85 99 88 83 105 113
# CLEARY NOT RANDOM!

Shuf 1-10

shuf -n1 -i1-10

# Shuffle 1-10
while [[ $COUNTER -le 1000 ]]; do
     RNUMS+=($(shuf -n1 -i1-10))
     COUNTER=$COUNTER+1
done
# and analysis
95 107 76 93 113 88 116 109 110
101 95 116 100 107 109 83 91 103
# GREAT RANDOM NUMBER GENERATOR


Fibonacci Counter In Pure Bash

The Fibonacci sequence is a mathematical sequence of numbers such that the result is the sum of the previous two numbers in the sequence starting at x=0 and y=1. Hence,

z = x + y

We can write a script to calculate this function in bash or shell commands.

First, I needed to visualize the idea:

x + y = z
z + y = z2

To help us figure this out we need to see what happens after the first iteration to work out how to change our variables and then send them through a loop.

x=0
y=1
z=0
# first time
z=$(( x + y ))
echo $z
Output~:$ 1

After the first time the sequence happens we need to add “x and y” again. On the second run z should be increased too. So how do we assign them?

# when we add x + y, then z became 1
# but now we need to to be replace y and then x for the second run.
# We can build a small tree to see what's happening

x   y   z
0 + 1 = 1
1 + 1 = 2
1 + 2 = 3
2 + 3 = 5
3 + 5 = 8
5 + 8 = 13
8 + 13= 21

# the z comes from nowhere else but the result of what we are about to do
# but we now know what we need to use in the second run, third run, and so on.
# We should make x now become y
x=$y

# and then y become z! $y needs to be give its value to x right
# before we give $y a new value from $z
y=$z

Now, how do we loop it? We can use a while loop. This while loop simply checks if $x is true. Whenever $x has a value, it will run. Hence, it will run forever.

y=1
while true; do
  let z=x+y
  echo $z
  x=$y
  y=$z
done

Here’s the result:

[[email protected] ~]$ y=1
[[email protected] ~]$ while true; do
>   let z=x+y
>   echo $z
>   x=$y
>   y=$z
> done
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
102334155
165580141
267914296
433494437
701408733
1134903170
1836311903
2971215073
4807526976
7778742049
12586269025
20365011074
32951280099
53316291173
86267571272
139583862445
225851433717
365435296162
591286729879
956722026041
1548008755920
2504730781961
4052739537881
6557470319842
10610209857723
17167680177565
27777890035288
44945570212853
72723460248141
117669030460994
190392490709135
308061521170129
498454011879264
806515533049393
1304969544928657
2111485077978050
3416454622906707
5527939700884757
8944394323791464
14472334024676221
23416728348467685
37889062373143906
61305790721611591
99194853094755497
160500643816367088
259695496911122585
420196140727489673
679891637638612258
1100087778366101931
1779979416004714189
2880067194370816120
4660046610375530309
7540113804746346429
-6246583658587674878
1293530146158671551
-4953053512429003327
-3659523366270331776
-8612576878699335103
6174643828739884737
-2437933049959450366
3736710778780434371
1298777728820984005
5035488507601418376
6334266236422402381
-7076989329685730859
-742723093263328478
-7819712422949059337
-8562435516212387815
2064596134548104464
-6497839381664283351
-4433243247116178887
7515661444929089378
3082418197812910491
-7848664430967551747
-4766246233154641256
5831833409587358613
1065587176432717357
6897420586020075970
7963007762452793327
-3586315725236682319
4376692037216111008
790376311979428689
5167068349195539697
5957444661174968386
-7322231063339043533
-1364786402164075147
-8687017465503118680
8394940206042357789
-292077259460760891
8102862946581596898
7810785687120836007
-2533095440007118711
5277690247113717296
2744594807106598585
8022285054220315881
-7679864212382637150
342420841837678731
-7337443370544958419
-6995022528707279688
4114278174457313509
-2880744354249966179
1233533820207347330
-1647210534042618849
-413676713835271519
-2060887247877890368
-2474563961713161887
-4535451209591052255
-7010015171304214142
6901277692814285219
-108737478489928923

bulk Delete Comment Spam From Existing Blacklist

To bulk delete comments, we are going to use phpmyadmin. Most hosting panels have /phpmyadmin active on your account.

Log into phpmyadmin and click on your database on the LEFT, then wp_comments or whatever database prefix you are using.

Then head to Search

Bulk Delete Comment Spam From WordPress
Bulk Delete Comment Spam From WordPress

Scroll down to comment_content and set the Operator column to %LIKE%, which matched wildcard anything before or after your term.

For this example, we are going to use the word sex:

Bulk Search and Delete from WordPress Comment Database
Bulk Search and Delete from WordPress Comment Database

You will receive a valid SQL query that we are going to reuse.

Bulk Search Comments WordPress Then Delete
Bulk Search Comments WordPress Then Delete

All you need to do is replace SELECT * with DELETE FROM

WARNING: If you have any of the terms elsewhere in your comments database, they will be deleted.

Don’t do this if you don’t know what you are doing.

Now, get your Comment Blacklist ready.

Open Text Mechanic here so we can prefix and suffix our list: https://textmechanic.com/text-tools/basic-text-tools/add-prefixsuffix-into-line/

Paste your comment spam blacklist at the top.

Add the Prefix as DELETE FROM…..%

And the Suffix as %’;

Don’t forget the ; at the end as we are using multiple lines

Delete Comment Spam Bulk From WordPress Blacklist SQL
Delete Comment Spam Bulk From WordPress Blacklist SQL

Then in phpmyadmin paste your list of SQL deletions into the SQL section and press SIMULATE QUERY

Bulk Delete WordPress Comments Table WordPress
Bulk Delete WordPress Comments Table WordPress

Anti-warning: since this is our actual “comment blacklist” already from the WordPress comments section, these comments would not have passed the filter anyway.

Simulate Query will show you what will be deleted when you press Go.

MYSQL Bulk Delete WordPress Comment Query
MYSQL Bulk Delete WordPress Comment Query

If all looks good, close the simulated query window and hit GO to permanently delete comments on your WordPress database that match your blacklist.

Wordpress Comment Spam Before
WordPress Comment Spam Before

My comment database went from 6000 to 1500!

Wordpress Comment Spam After
WordPress Comment Spam After

My comment blacklist can be downloaded here.