Specify/rename a directory with tar (when provisioning AWS)

I use ffmpeg, the famed media swiss army knife, to handle some of the audio conversion tasks in my record label management app, which is a pretty straightforward Laravel 8 thing running on a tiny and cheap AWS Elastic Beanstalk Linux instance.

Whenever I push changes to the app, my workflow is to create and provision a brand new instance using the eb cli with the usual salad of yaml files, run eb swap when it’s all green and healthy, then eb terminate the redundant instance. The MongoDB database is completely separate over on Atlas so I don’t even need to think about that, deploys are usually fairly painless.

A url to download the latest release build for ffmpeg is handily provided by John Van Sickle over at John Van Sickle - FFmpeg Static Builds

Originally my provisioning command looked something like this:

  03_install_ffmpeg_command:
    # If ffmpeg install is failing, the version number might need to be updated.
    command: |
      cd /usr/local/bin
      wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
      sudo tar -xf ffmpeg-release-amd64-static.tar.xz
      sudo mv ffmpeg-4.3.1-amd64-static ffmpeg
      sudo ln -s /usr/local/bin/ffmpeg/ffmpeg /usr/bin/ffmpeg
      sudo ln -s /usr/local/bin/ffmpeg/ffprobe /usr/bin/ffprobe      

We get the build, untar it in place, rename/move it, and then symlinks ftw. This works fine until there is an update to ffmpeg, and that directory name which includes the version number changes, and the deploy breaks silently. I’d usually been discovering this when the mp3 conversion tasks just stopped working - that’s what that note to self comment is all about.

Now yes I could probably do with some better tests and error catching in the app itself but I don’t really want to have to think about ffmpeg versioning at all, and I’d rather everything just worked automagically. It’s man page time!

$ man tar

Scrolling through the reams of of text, it turns out tar has two useful options which we can make use of here.

-C directory, –cd directory, –directory directory In c and r mode, this changes the directory before adding the following files. In x mode, change directories after opening the archive but before extracting entries from the archive.

–strip-components count Remove the specified number of leading path elements. Pathnames with fewer elements will be silently skipped. Note that the pathname is edited after checking inclusion/exclusion pat- terns but before security checks.

So essentially, -C cd’s into a directory before untarring, and --strip-components removes a specific number of top level directories from the result. We can therefore create the directory first with mkdir and then untar into that while removing the first path level with the version number.

  03_install_ffmpeg_command:
    command: |
      cd /usr/local/bin
      wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
      sudo mkdir ffmpeg
      sudo tar -xf ffmpeg-release-amd64-static.tar.xz -C ffmpeg --strip-components=1
      sudo ln -s /usr/local/bin/ffmpeg/ffmpeg /usr/bin/ffmpeg
      sudo ln -s /usr/local/bin/ffmpeg/ffprobe /usr/bin/ffprobe      

Tada! No more broken ffmpeg updates.

Record labels yeah? Check them out over here: