Over The Air Shell Scripts

So you just finished writing this super awesome shell script, now the question is “How do I run it?”. There are many ways you can run a shell script. You can run a script locally, run a local script on a remote server via ssh, or you can copy and run it directly on a remote server.

But wait, did you know there is another option?! You can run a script directly from a remote server “over the air.” Let’s dig in.

This method is commonly used to install command line applications.

When installing a new command on the command line, you’ll typically grab a one line installation command. That command simply downloads a shell script and runs it. The shell script, which you generally never see, is what really installs the application, not some simple one line installation command. Take a look at Rclone’s one liner curl https://rclone.org/install.sh | sudo bash. If you peak at their install.sh script you’ll see it’s doing clever things like checking what your computer platform is, which compression utilities are installed, and then the logic for actually installing Rclone.

This isn’t just a good way to install something, it can be used for any script!

As long as the script is safe and trusted, you can absolutely use this method to run any shell script on any computer without any prerequisites. The script should be smart enough so that it’s not accidentally run on a system it’s not compatible with, or bail if one of it’s own prerequisites are not meet.

Supporting script arguments and short links.

I’m going to show you how to run my migrations script, which is bundled within CaptainCore toolkit, directly without having to install CaptainCore. The script file is located here: https://raw.githubusercontent.com/CaptainCore/captaincore-cli/master/lib/remote-scripts/migrate. In order keep this simple I setup a redirection rule so we can use https://captaincore.io/run/migrate instead.

With Curl we need to use the argument -L to follow the redirection shortcut. The migration script also requires arguments. In order to properly pass arguments to the script we need to add -- between bash -s and the scripts arguments. Otherwise our script arguments would accidentally get passed to bash itself which will not work. We’ll run the script using this format.

curl -L https://captaincore.io/run/$script | bash -s -- --argument="$value"

Even better with a Cloudflare Worker.

We can remove the need to follow a redirection if we setup a Cloudflare Worker. The following worker will take one of my CaptainCore commands and then fetch the respond if that command is found.

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event, event.request))

async function handleRequest(event, request) {
  url = new URL( request.url )
  commands = [ "apply-https", "db-backup", "deploy-fathom", "fetch-site-data", "master-db-query", "prepare-wordpress", "update", "apply-https-with-www", "db-convert-to-innodb", "deploy-helper", "kickstart", "migrate", "reset-permissions", "verify-google-analytics-takeover", "arguments", "db-import", "deploy-mailgun", "launch", "plugins-zip", "rewrite-prep" ]
  command = url.pathname.replace( "/", "" )

  if ( ! commands.includes( command ) ) {
    return new Response( `Not found.`, { status: 404 } )

  return fetch( `https://raw.githubusercontent.com/CaptainCore/cli/master/lib/remote-scripts${url.pathname}` )


Here is what the improved usage looks like using the Cloudflare worker.

curl https://run.captaincore.io/$script | bash -s -- --argument="$value"

Migrating a site to Kinsta using a remote script.

This one liner will perform a site migration using CaptainCore’s migration script. This works great with Kinsta’s SSH using screen -R as a background process. The variable $url needs to be a public accessible backup snapshot. Warning this will overwrite the current Kinsta WordPress website and it not tested with other WordPress web hosts.

curl https://run.captaincore.io/migrate | bash -s -- --url="$url" --update-urls

Few other examples from the CaptainCore toolkit.

Reset default file and folder permissions

curl https://run.captaincore.io/reset-permissions | bash -s

Convert MyISAM database tables to InnoDB

curl https://run.captaincore.io/db-convert-to-innodb | bash -s

Launches WordPress site by updating URL from dev to live, enabling search engine and clearing cache. Change or set variables $site to be the site name and $domain to be the domain you wish to use for your live WordPress site.

curl https://run.captaincore.io/launch | bash -s -- --site=$site --domain=$domain