How to Update Perl in Linux (Safely): Package Managers, perlbrew, and Source Builds

Question

how to update perl in linux

Difficulty

Intermediate (beginner-friendly steps included, but choices affect system stability).

Tags

perl, linux, package-management, perlbrew, cpan, cpanminus, build-from-source, devops

Overview: What “updating Perl” really means

On Linux, “updating Perl” can mean different things depending on where your Perl comes from and how it’s used:

  • System Perl: The Perl interpreter provided by your distribution (Debian/Ubuntu, RHEL/Fedora, Arch, Alpine, etc.). Many OS tools and packages may rely on it.
  • User-managed Perl: A separate Perl you install for your own apps (often via perlbrew or plenv), without touching the system Perl.
  • Modules: CPAN modules (dependencies) are separate from the Perl interpreter version; you may need to update them too.

The safest default is: leave the system Perl alone and install a newer Perl for your applications using a version manager (usually perlbrew).

Step 0: Identify what you currently have

Before changing anything, confirm which Perl is being used and what version it is:

which perl
perl -v
perl -e 'print "Perl executable: $^X\nPerl version: $^V\n"'

Why this matters: You might have multiple Perls (for example, /usr/bin/perl and a user-installed one in $HOME/perl5), and the one first on $PATH is the one you actually run.

Option A (recommended for system stability): Update Perl via your Linux package manager

This updates Perl within the constraints of your distribution release. It’s the right choice if you want the vendor-supported Perl, security updates, and minimal surprises.

Debian/Ubuntu

sudo apt update
sudo apt install --only-upgrade perl
# or update everything (common on servers you manage as a unit)
sudo apt full-upgrade

Notes: On stable distributions, Perl may not jump to the newest major/minor line. You get the distro’s supported version plus security patches.

Fedora

sudo dnf upgrade perl
# or upgrade all packages
sudo dnf upgrade

RHEL/CentOS/Rocky/Alma

sudo dnf upgrade perl
# older systems may use yum
sudo yum update perl

Notes: Enterprise distributions often ship older Perl versions intentionally. If you need newer, use Option B (perlbrew) rather than forcing the OS Perl to change.

Arch Linux

sudo pacman -Syu perl

Alpine Linux

sudo apk update
sudo apk upgrade perl

openSUSE/SLES

sudo zypper refresh
sudo zypper update perl

Best practice for package-manager updates

  • Do not “replace” /usr/bin/perl manually. Let the OS own it.
  • After upgrading, re-check: perl -v and run your app’s test suite.
  • If your project depends on a specific Perl line, pin it via a user-managed Perl (Option B), containers, or CI matrices.

Option B (best for apps): Install and update Perl using perlbrew (user-managed)

perlbrew installs Perls into your home directory and lets you switch versions per shell or per project. This is the most common way to get a newer Perl on a server without risking OS breakage.

Install perlbrew

curl -L https://install.perlbrew.pl | bash
# then add perlbrew init to your shell (bash/zsh). Example (zsh):
echo 'source "$HOME/perl5/perlbrew/etc/bashrc"' >> ~/.zshrc
# reload your shell
exec $SHELL -l
perlbrew --version

Install a new Perl and switch to it

# list available perls
perlbrew available

# install a specific Perl (example)
perlbrew install perl-5.38.2

# switch your current shell to that Perl
perlbrew use perl-5.38.2

# make it default for future shells
perlbrew switch perl-5.38.2

# confirm
which perl
perl -v

Install modules for that Perl (recommended: cpanminus)

perlbrew install-cpanm
cpanm --version

Each perlbrew-installed Perl has its own library path. That’s good: you avoid mixing modules compiled for different Perls.

Why perlbrew is safer than “upgrading system Perl”

  • Your OS keeps using its supported Perl for system utilities.
  • Your application uses a newer Perl (and you can have multiple versions side-by-side).
  • Rollbacks are easy: just perlbrew switch back.

Option C (advanced): Build Perl from source (without clobbering system Perl)

Building from source is sometimes needed for custom compile options, older distros, offline environments, or when you can’t (or don’t want to) use perlbrew. The main rule: install to a custom prefix (e.g., /opt/perl or $HOME/perl), not into /usr.

High-level process

  1. Install build dependencies (compiler toolchain, development headers).
  2. Download a Perl source tarball from perl.org.
  3. Configure with a safe prefix.
  4. make, make test, then make install.
  5. Update your PATH (or use modulefiles) so your app uses the new Perl.

Example build (prefix in /opt/perl-5.38.2)

tar -xzf perl-5.38.2.tar.gz
cd perl-5.38.2
./Configure -des -Dprefix=/opt/perl-5.38.2
make -j"$(nproc)"
make test
sudo make install

# then use it explicitly:
/opt/perl-5.38.2/bin/perl -v

Common dependency pitfall: if you compile XS modules (modules with C code) later, you’ll need development tools and headers installed (and sometimes perl-devel / libperl equivalents depending on distro).

Updating CPAN modules after updating Perl

When you install a new Perl (especially via perlbrew or source), you often start with an empty site library. That’s normal. Update/install your project’s dependencies in a controlled way:

  • Prefer cpanminus: cpanm is scriptable and CI-friendly.
  • Avoid sudo cpan for app dependencies; it tends to pollute system paths and can conflict with distro packages.
  • Project isolation: for non-perlbrew setups, consider local::lib to keep modules in a project/user directory.

Example: install modules into a user library with local::lib

# one-time setup
perl -MCPAN -e 'install local::lib'

# initialize environment (example; local::lib prints a snippet you can eval)
perl -Mlocal::lib

# then install modules into that local lib
cpanm --local-lib=~/perl5 Some::Module Another::Module

Best practices (production-friendly)

  • Don’t break the OS: keep the system Perl for the OS; use perlbrew/source-per-prefix for apps.
  • Pin interpreter + dependencies per project: document the required Perl version (e.g., “Perl >= 5.34”) and install modules deterministically (lockfiles via tools like Carton if your ecosystem uses it).
  • Be explicit in services: in systemd units or cron jobs, use the full path to the intended Perl (e.g., /opt/perl-5.38.2/bin/perl) to avoid $PATH surprises.
  • Test after upgrade: run unit/integration tests, and at minimum execute a smoke test that loads your key modules.
  • Plan rollback: keep the previous Perl installed until you’ve run in production for a while. perlbrew makes this trivial.
  • Watch XS modules: modules with C components must be rebuilt for the new Perl (they are not generally portable across Perl builds).

Common pitfalls and how to avoid them

  • Accidentally changing /usr/bin/perl: Don’t overwrite it. Use version managers or custom prefixes.
  • Mixing distro modules and CPAN modules: If you install modules with sudo into system locations, you can cause conflicts with OS package updates. Prefer isolated installs.
  • Confusing multiple Perls: which perl might differ between interactive shells, cron, and systemd. Always validate in the same context your app runs.
  • Forgetting to reinstall modules: A new Perl often needs dependencies reinstalled (especially XS). Automate with cpanm and a dependency list.
  • Shebang mismatch: Scripts starting with #!/usr/bin/perl will continue to use system Perl even if you installed a newer one. For app scripts, consider #!/usr/bin/env perl or a fixed absolute path.
  • Assuming “latest Perl” is required: Sometimes the best move is to stay on a distro Perl and only update modules, unless you need language/runtime features or security fixes not backported.

Real-world usage patterns

  • Legacy server + modern app: Keep OS Perl stable, install Perl 5.38+ via perlbrew for your service, and point systemd to that Perl.
  • CI/CD matrix testing: Use multiple Perl versions in CI to ensure compatibility (e.g., lowest supported, current stable).
  • Containers: Choose a base image with the Perl you want (or install via perlbrew during build), ensuring deployments are reproducible.
  • Multi-tenant hosts: perlbrew per user prevents one project’s dependencies from breaking another’s.

Runnable Perl code examples

Example 1: Simple smoke test (works everywhere)

use strict;
use warnings;

print "Hello from Perl\n";
print "OK\n";

Expected output:

Hello from Perl
OK

Example 2: Check the running Perl version (useful after an upgrade)

use strict;
use warnings;

print "Perl executable: $^X\n";
print "Perl version: $^V\n";

Expected output (example; your paths/versions will differ):

Perl executable: /home/user/perl5/perlbrew/perls/perl-5.38.2/bin/perl
Perl version: v5.38.2

Example 3: Verify a core module + deterministic output (good for automation)

use strict;
use warnings;
use Digest::SHA qw(sha256_hex);

my $msg = "update-perl";
print sha256_hex($msg), "\n";

Expected output:

7a585c2b3de904804bb247e1fcd10b8b6e812207d9e7382c907ee088051dd71c

Quick decision guide

  • If you administer a server and want vendor support: update via package manager (Option A).
  • If you develop/deploy apps and need newer Perl features: use perlbrew (Option B).
  • If you need custom builds or can’t use perlbrew: build from source with a custom prefix (Option C).

Verified Code

Executed in a sandbox to capture real output. • 13ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
7a585c2b3de904804bb247e1fcd10b8b6e812207d9e7382c907ee088051dd71c
STDERR
(empty)

Was this helpful?