Linux Tools Apt-Mirror And Systemd-nspawn Are Super Effective

Alright, let’s explore two specific tools for productivity elevation. Namely, systemd-nspawn1 and apt-mirror2.

I can show you the brief interactions I have had with these in recent times and how beneficial those could be in the general sense.

Apt-mirror is to create a local mirror of the upstream mirror

What does that mean? Simple, something hosted remotely and publicly available that can be brought down to your local machine for your inspection and improvements et.al.

Okay, a little demo won’t hurt much 🙂 , here are some ways:

Installation

Oh, you are supposed to get it by the debian package manager and it’s darn simple.

apt-get install apt-mirror

Now, it brings down a few files with it, especially two files that should interest us for the usability of this tool. Which are /etc/apt/mirror.list and /etc/cron.d/apt-mirror . And we will tweak a little to fulfill our needs.

############# config ##################
#
 set base_path    /home/bhaskar/apt-mirrors
#
# set mirror_path  $base_path/mirror
# set skel_path    $base_path/skel
# set var_path     $base_path/var
# set cleanscript $var_path/clean.sh
# set defaultarch  <running host architecture>
# set postmirror_script $var_path/postmirror.sh
# set run_postmirror 0
set nthreads     20
set _tilde 0
#
############# end config ##############
# deb http://ftp.us.debian.org/debian bookworm main contrib non-free
# deb-src http://ftp.us.debian.org/debian bookworm main contrib non-free

# mirror additional architectures
#deb-alpha http://ftp.us.debian.org/debian unstable main contrib non-free
deb-amd64 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-armel http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-hppa http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-i386 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-ia64 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-m68k http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-mips http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-mipsel http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-powerpc http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-s390 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-sparc http://ftp.us.debian.org/debian unstable main contrib non-free

clean http://ftp.us.debian.org/debian

You see, I have changed three things in the above file. First, I created a directory under my home directory called apt-mirrors and fixed the base_path variable with it. Heads up! You are supposed to create the directory in places where some hefty amount of free space is available. This operation needs a placeholder big in some hundreds of Gibs, otherwise you might not accommodate it.

Then I commented on the two lines right after the end config marker. You might keep that if you want to. Because those are defaults and it will certainly pull from there.

Next, I uncommented one line specifically some architecture-specific i.e. an amd64-related line, so it pulls from that source.

Once you made changes to the mirror.list file then you are supposed to run this command as a superuser, as the manual said to get a sync.

sudo apt-mirror -c apt-mirror

Well, we are now all set. Let’s see how it goes …

2024-04-25-072311_1920x1200_scrot.png

See! It is quite big, a whooping 143 gig, but that is okay to get the entire repo.

And the last thing about this is that, once you get the content down to your local machine you probably want to have it frequently after certain intervals with the updates. Here comes the importance of having a cron file attached to it. This software brings along a file with it and it looks like this :

#
# Regular cron jobs for the apt-mirror package
#
#0 4    * * *   apt-mirror      /usr/bin/apt-mirror > /var/spool/apt-mirror/var/cron.log

You can change the value of this cron entry at your convenience, so you don’t have to do it by hand when you need it.

Systemd-nspawn is a more popular tool in the modern era

How so? Because distributions running(whether in enterprise or person) Systemd should take advantage of this tool. In crux, this is a modern way of doing chroot in systemd specific systems.

There are various use cases to use this tool and on top of my head, I could be using it to test some new stuff about some arcane thing in the restricted environment. So, it isolates the host system from getting banged by some experimentation done in the confined area of your machine. (aka containerized way of doing things).

Here I am showing you the abject ordinary thing this tool can help by running two different Linux distributions in a confined area of the machine. I am sitting on Debian3,i.e. the host system, and going to try our latest version of fedora404 and openSUSE Tumbleweed5 , which is installed in different physical partitions in the same machine.

First, take openSUSE Tumbleweed, and this is how boots with the help of this tool :

#!/usr/bin/env bash

if test $UID -ne 0;then
        echo you are suppose to run this as superuser
        exit 1
fi

if test ! -d /OpenSuseTW;then
        mkdir -p /OpenSuseTW
fi

echo Mounting.....

/bin/mount /dev/nvme0n1p8 /OpenSuseTW


systemd-nspawn -bD /OpenSuseTW

Pretty simple! Right. I said in the above vignette that this particular distribution is already installed in other physical partitions. Just created a directory to hold the mounted partition and boot from it to provide the login prompt and you can use the normal login credential, which you probably created when installed it.

The -b flag is for the booting and

The -D flag is for providing the shell.

Likewise, using this same tool i.e. systemd-nspawn ,I can spin up a minimal fedora version in a quick time. The system-nspawn man page clearly states how to do it.

Prerequisite :

You are supposed to install dnf beforehand to make things easy to do this kind of stuff. Again the manual clearly states that.

Here is how I put all those in an ordinary script to do the job for me:

#!/usr/bin/env bash

# To get the cloud image

# machinectl pull-raw --verify=no https://download.fedoraproject.org/pub/fedora/linux/releases/38/Cloud/x86_64/images/Fedora-Cloud-Base-38-1.6.x86_64.raw.xz fedora38

# systemd-nspawn -M fedora38

# Another way of getting minimal stuff

# if test $(which dnf) == "";then
#       pkg_install dnf
# fi
# dnf -y --releasever=40 --installroot=/srv/fedora40 --disablerepo='*' --enablerepo=fedora --enablerepo=updates install systemd util-linux iputils passwd dnf fedora-release  vim-minimal
# systemd-nspawn -D /srv/fedora40 ----> to set the root password
#
if test $UID -ne 0;then
     echo you are suppose to run this as superuser
     exit 1
fi

if test ! -d /srv/fedora40;then
     mkdir -p /srv/fedora40
fi

unlink /srv/fedora40/etc/resolv.conf

cp /etc/resolv.conf /srv/fedora40/etc/resolv.conf

systemd-nspawn -bD /srv/fedora40

I have commented on the DNF-related lines because I had it before I made the script. Oh, that pkg_install is nothing but a wrapper over the underlying package manager used by the host distributions. I have made a few steps explicit because it was hindering smooth operation, although you could ignore the unlink and cp steps. Those are ugly workarounds in my convoluted environment. In your case, those are not necessary.

Last, if you are the kind of person, who are getting excited by seeing in a different form than this writing, then I have at least a video about apt-mirror on YouTube.

Emacs And Vim Inflate Them For The Sake Of Usefulness?

Well, you might argue that it is a pure skill issue. And believe me, I don’t disagree with you. Every good thing comes with a package of burden, whether it is apparent or not at first glance, but gradually shows its colors.

I have leaned on two of the best editors ( no kidding, fellas) and stuck with them forever. And as a result, I have grown some soft spot for them. The funny part is that I haven’t tried to escape from that fondness. So hooked, that I even looked for something that gives so much pain to integrate and operate on those, considering the vast availability of solutions posted by the experts of those systems.

The end result is awesome and I have had a soothing experience for many years now. The hassle become less and know-how has greatly improved, still a lot to be desired.

Here is a glimpse of one of my editors of choice i.e. Emacs1 below for your perusal in terms of the capabilities included in it.

ls -al ~/.emacs.d/elpa | gawk '{ print $9 }'
#+RESULTS:
|                                              |
| .                                            |
| ..                                           |
| ace-jump-mode-20140616.815                   |
| alert-20221213.1619                          |
| all-the-icons-20220117.108                   |
| all-the-icons-20220325.1238                  |
| all-the-icons-dired-20231207.1324            |
| all-the-icons-ibuffer-20230503.1625          |
| all-the-icons-ivy-20190508.1803              |
| all-the-icons-ivy-rich-20220510.752          |
| all-the-icons-ivy-rich-20230314.1559         |
| all-the-icons-ivy-rich-20230420.1234         |
| amx-20230413.1210                            |
| annotate-20231102.1334                       |
| annotation-20200914.644                      |
| apiwrap-20180602.2231                        |
| archives                                     |
| async-20240106.1448                          |
| async-await-20220827.437                     |
| auto-complete-20240101.831                   |
| avy-20230420.404                             |
| biblio-20230202.1721                         |
| biblio-core-20230202.1721                    |
| bibtex-completion-20240107.1150              |
| bibtex-utils-20190703.2117                   |
| bind-key-20230203.2004                       |
| bitbucket-20170405.446                       |
| browse-at-remote-20230223.554                |
| chronos-20230804.1712                        |
| circadian-20231027.744                       |
| citar-20231226.1453                          |
| citar-denote-20231229.531                    |
| citar-embark-20231122.1548                   |
| citar-org-roam-20230404.1225                 |
| citeproc-20231230.1309                       |
| cl-libify-20181130.230                       |
| closql-20240101.2212                         |
| command-log-mode-20160413.447                |
| company-20240107.2310                        |
| compat-29.1.4.4                              |
| compat-29.1.4.4.signed                       |
| connection-20191111.446                      |
| consult-20220319.2221                        |
| consult-20220508.928                         |
| consult-20230326.2048                        |
| counsel-20231025.2311                        |
| counsel-notmuch-20181203.935                 |
| crux-20231013.520                            |
| ctags-update-20190609.613                    |
| dash-20240103.1301                           |
| dashboard-20220516.456                       |
| dashboard-20230328.610                       |
| dashboard-project-status-20190202.1354       |
| deferred-20170901.1330                       |
| define-word-20220104.1848                    |
| deft-20210707.1633                           |
| denote-2.2.4                                 |
| denote-2.2.4.signed                          |
| dictionary-20201001.1727                     |
| dired-git-20220828.6                         |
| dired-git-info-0.3.1                         |
| dired-git-info-0.3.1.signed                  |
| dired-icon-20170223.526                      |
| dired-rsync-20230822.1350                    |
| dired-single-20230306.626                    |
| dired-toggle-20190616.303                    |
| djvu-1.1.2                                   |
| djvu-1.1.2.signed                            |
| doom-modeline-20220325.554                   |
| doom-modeline-20220412.853                   |
| doom-modeline-20220515.1603                  |
| doom-modeline-20230306.250                   |
| doom-themes-20231208.2011                    |
| eglot-20211009.1931                          |
| eglot-20211215.2131                          |
| eglot-20220123.1406                          |
| eglot-20220302.1035                          |
| eglot-20220329.1217                          |
| eglot-20220415.1822                          |
| eglot-20220509.1904                          |
| eglot-20221020.1010                          |
| el2org-20200408.146                          |
| elfeed-20221108.755                          |
| elfeed-goodies-20221003.1406                 |
| elisp-refs-20230920.201                      |
| emacs-everywhere-20220515.346                |
| emacs-everywhere-20220831.1636               |
| emacs-everywhere-20230706.1152               |
| emacsql-20230417.1448                        |
| emacsql-sqlite-20230225.2205                 |
| emacsql-sqlite3-20200914.508                 |
| emacsql-sqlite3-20220304.1014                |
| embark-20220329.505                          |
| embark-20220421.1436                         |
| embark-20220509.2259                         |
| embark-20230328.1813                         |
| embark-consult-20220329.32                   |
| embark-consult-20220419.2029                 |
| embark-consult-20220507.143                  |
| embark-consult-20230327.1843                 |
| emms-20220315.1727                           |
| emms-20220422.1318                           |
| emms-20230328.2021                           |
| emojify-20210108.1111                        |
| engine-mode-20230619.1503                    |
| enlive-20170725.1417                         |
| epl-20180205.2049                            |
| esup-20220202.2335                           |
| esxml-20230308.2254                          |
| f-20231219.750                               |
| ffmpeg-player-20240101.926                   |
| flx-20221213.542                             |
| flx-ido-20221213.542                         |
| flycheck-20230813.620                        |
| flycheck-grammarly-20240101.847              |
| flyspell-correct-20220520.630                |
| flyspell-correct-popup-20220520.630          |
| font-utils-20210405.1149                     |
| forge-20220329.2038                          |
| forge-20220422.1609                          |
| forge-20220506.420                           |
| forge-20230326.2058                          |
| general-20230311.1229                        |
| ghub+-20191229.1748                          |
| ghub-20220329.2141                           |
| ghub-20220422.1610                           |
| ghub-20220429.1708                           |
| ghub-20230301.1402                           |
| git-20140128.1041                            |
| git-commit-20220328.47                       |
| git-commit-20220422.1903                     |
| git-commit-20220506.1936                     |
| git-commit-20230313.1724                     |
| git-commit-20240101.2229                     |
| git-commit-insert-issue-20230512.1416        |
| git-messenger-20201202.1637                  |
| git-timemachine-20230630.1214                |
| gntp-20141025.250                            |
| gnupg                                        |
| goto-line-preview-20240101.855               |
| grammarly-20240101.846                       |
| grapnel-20131001.1534                        |
| grip-mode-20230206.323                       |
| gscholar-bibtex-20190130.555                 |
| helm-20220319.1850                           |
| helm-20220421.806                            |
| helm-20220513.1002                           |
| helm-20230319.2009                           |
| helm-bibtex-20231009.1014                    |
| helm-core-20220319.1850                      |
| helm-core-20220422.706                       |
| helm-core-20220514.725                       |
| helm-core-20230317.1729                      |
| helm-org-20231022.620                        |
| helm-pass-20210221.1655                      |
| helpful-20220513.302                         |
| helpful-20230323.414                         |
| highlight-parentheses-20220408.845           |
| hl-todo-20240101.2217                        |
| hnreader-20221117.650                        |
| ht-20230703.558                              |
| htmlize-20210825.2150                        |
| hydra-20220910.1206                          |
| i3wm-20170822.1438                           |
| i3wm-config-mode-20220913.1121               |
| imenus-20200730.855                          |
| insert-shebang-20201203.1648                 |
| iter2-20221104.1938                          |
| ivy-20231025.2311                            |
| ivy-bibtex-20210927.1205                     |
| ivy-posframe-20211217.234                    |
| ivy-rich-20230425.1422                       |
| ix-20131027.1657                             |
| key-chord-20230522.223                       |
| keycast-20240105.1258                        |
| keychain-environment-20180318.2223           |
| keytar-20240101.846                          |
| kv-20140108.1534                             |
| langtool-20230222.326                        |
| leaf-20230803.729                            |
| link-20191111.446                            |
| link-hint-20231225.1354                      |
| list-utils-20230422.1740                     |
| log4e-20240107.1036                          |
| lsp-grammarly-20221231.1655                  |
| lsp-mode-20220328.1429                       |
| lsp-mode-20220422.2059                       |
| lsp-mode-20220514.1948                       |
| lsp-mode-20230328.1623                       |
| lv-20200507.1518                             |
| macrostep-20230813.2123                      |
| magit-20240102.1752                          |
| magit-org-todos-20180709.1950                |
| magit-popup-20200719.1015                    |
| magit-section-20220422.1903                  |
| magit-section-20220513.1429                  |
| magit-section-20230314.1653                  |
| magit-section-20240101.2229                  |
| magit-todos-20231216.1205                    |
| magit-topgit-20161105.1623                   |
| magithub-20220315.117                        |
| marginalia-20220312.1357                     |
| marginalia-20220417.418                      |
| marginalia-20220426.449                      |
| marginalia-20230317.926                      |
| mark-multiple-20121118.1554                  |
| markdown-mode-20220513.1453                  |
| markdown-mode-20230326.954                   |
| metaweblog-20230501.234                      |
| mini-modeline-20230306.1521                  |
| mode-icons-20230911.20                       |
| molokai-theme-20220106.1520                  |
| monokai-theme-20220117.1244                  |
| move-text-20231204.1514                      |
| mu4e-alert-20230722.1746                     |
| mu4e-marker-icons-20230423.1039              |
| mu4e-views-20230105.1443                     |
| multi-20131013.1544                          |
| multi-vterm-20221031.610                     |
| multiple-cursors-20230728.518                |
| mustache-20230713.514                        |
| neotree-20230815.219                         |
| nerd-icons-20231231.710                      |
| nerd-icons-dired-20231214.2155               |
| noflet-20141102.1454                         |
| notmuch-20231006.2337                        |
| notmuch-maildir-20240101.2221                |
| orderless-20220312.1944                      |
| orderless-20220418.2119                      |
| orderless-20230219.1648                      |
| org-alert-20231104.1236                      |
| org-beautify-theme-20170908.2218             |
| org-books-20210408.1913                      |
| org-bullets-20200317.1740                    |
| org-capture-pop-frame-20230516.236           |
| org-dashboard-20171223.1924                  |
| org-download-20220906.1929                   |
| org-fancy-priorities-20210830.1657           |
| org-inline-pdf-20230826.1220                 |
| org-mime-20220515.736                        |
| org-mime-20230321.2341                       |
| org-msg-20230530.2006                        |
| org-noter-20231205.37                        |
| org-noter-pdftools-20230725.1433             |
| org-pdftools-20220320.301                    |
| org-pomodoro-20220318.1618                   |
| org-pretty-tags-20211228.1546                |
| org-preview-html-20220809.1033               |
| org-protocol-jekyll-20170328.1639            |
| org-ref-20220327.1635                        |
| org-ref-20220331.2336                        |
| org-ref-20220509.1414                        |
| org-ref-20230312.1711                        |
| org-ref-prettify-20220507.649                |
| org-roam-20220304.647                        |
| org-roam-20220327.1811                       |
| org-roam-20220417.332                        |
| org-roam-20220515.2351                       |
| org-roam-20230307.1721                       |
| org-roam-bibtex-20220213.1609                |
| org-roam-bibtex-20230201.1834                |
| org-roam-bibtex-20230628.2036                |
| org-roam-server-20210521.1055                |
| org-tag-beautify-20230316.419.backup         |
| org-timeline-20211110.1952                   |
| org-web-tools-20231220.1515                  |
| org2blog-20230501.2319                       |
| org2web-20210203.324                         |
| ov-20230522.1117                             |
| ox-pandoc-20231222.1103                      |
| page-break-lines-20230804.658                |
| parsebib-20230228.1530                       |
| pass-20231206.736                            |
| password-menu-20240407.2241                  |
| password-store-20231201.954                  |
| password-store-otp-20220128.1320             |
| pcache-20220724.1841                         |
| pcre2el-20230828.1544                        |
| pdf-tools-20220418.1555                      |
| pdf-tools-20220512.145                       |
| pdf-tools-20230322.1541                      |
| pdf-tools-20230611.239                       |
| pdf-view-restore-20190904.1708               |
| peep-dired-20160321.2237                     |
| peg-1.0.1                                    |
| peg-1.0.1.signed                             |
| persist-0.5                                  |
| persist-0.5.signed                           |
| persistent-soft-20150223.1853                |
| pinentry-0.1                                 |
| pinentry-0.1.signed                          |
| pkg-info-20150517.1143                       |
| plz-0.7.1                                    |
| plz-0.7.1.signed                             |
| pocket-lib-20190720.1957                     |
| pocket-reader-20230904.539                   |
| popper-20220309.457                          |
| popper-20220406.336                          |
| popper-20230302.2055                         |
| popup-20240101.830                           |
| popup-complete-20141109.308                  |
| popup-edit-menu-20170404.1425                |
| popup-imenu-20210404.1153                    |
| popup-kill-ring-20131020.1854                |
| popup-switcher-20210402.1208                 |
| popwin-20210215.1849                         |
| pos-tip-20230721.834                         |
| posframe-20230714.227                        |
| powerline-20221110.1956                      |
| ppp-20220211.1529                            |
| prescient-20221216.112                       |
| pretty-symbols-20140814.959                  |
| projectile-20220227.551                      |
| projectile-20220329.937                      |
| projectile-20220419.1102                     |
| projectile-20220430.800                      |
| projectile-20230317.1101                     |
| promise-20210307.727                         |
| queue-0.2                                    |
| queue-0.2.signed                             |
| rainbow-delimiters-20210515.1254             |
| rainbow-identifiers-20141102.1526            |
| rainbow-mode-1.0.6                           |
| rainbow-mode-1.0.6.signed                    |
| reddigg-20240107.235                         |
| remember-last-theme-20170619.2133            |
| request-20230127.417                         |
| request-deferred-20220614.1604               |
| restart-emacs-20201127.1425                  |
| rich-minority-20190419.1136                  |
| s-20220902.1511                              |
| scratch-20220319.1705                        |
| selectrum-20220513.2106                      |
| selectrum-prescient-20231205.137             |
| shrink-path-20190208.1335                    |
| simple-httpd-20230821.1458                   |
| site-lisp-0.1.2                              |
| site-lisp-0.1.2.signed                       |
| smart-compile-20240102.1350                  |
| smart-mode-line-20211005.233                 |
| smart-mode-line-powerline-theme-20211005.233 |
| smex-20151212.2209                           |
| sml-mode-6.12                                |
| sml-mode-6.12.signed                         |
| solarized-theme-20231204.713                 |
| spell-fu-20230326.736                        |
| spell-fu-20230808.1342                       |
| spinner-1.7.4                                |
| spinner-1.7.4.signed                         |
| string-inflection-20220910.1306              |
| sudo-edit-20220801.1317                      |
| swiper-20231025.2311                         |
| swiper-helm-20180131.1744                    |
| synosaurus-20191125.552                      |
| tablist-20231019.1126                        |
| toc-org-20220110.1452                        |
| transient-20220130.1941                      |
| transient-20220227.1751                      |
| transient-20220325.1619                      |
| transient-20220422.1627                      |
| transient-20240106.1457                      |
| treepy-20230715.2154                         |
| ucs-utils-20230119.2237                      |
| undo-tree-0.8.2                              |
| undo-tree-0.8.2.signed                       |
| unicode-fonts-20230926.1502                  |
| vertico-0.23                                 |
| vertico-0.23.signed                          |
| vertico-1.2                                  |
| vertico-1.2.signed                           |
| vimrc-mode-20181116.1919                     |
| vterm-20220429.21                            |
| vterm-20230217.228                           |
| vterm-toggle-20230912.246                    |
| webpaste-20220524.1745                       |
| websocket-20230809.305                       |
| wfnames-20230924.1538                        |
| wgrep-20230203.1214                          |
| which-key-20220214.1818                      |
| which-key-20220419.227                       |
| which-key-20220518.1941                      |
| which-key-20220811.1616                      |
| with-editor-20220211.2034                    |
| with-editor-20220318.1640                    |
| with-editor-20220422.1628                    |
| with-editor-20220506.420                     |
| with-editor-20240101.2226                    |
| with-emacs-20220814.444                      |
| wordnut-20180313.443                         |
| writegood-mode-20220511.2109                 |
| wttrin-20170614.1206                         |
| xclip-1.11                                   |
| xclip-1.11.signed                            |
| xcscope-20230626.2109                        |
| xml-rpc-20231009.1432                        |
| xref-1.6.3                                   |
| xref-1.6.3.signed                            |
| xterm-color-20230321.3                       |
| xwidgets-reuse-20231205.1315                 |
| yaml-20231211.1501                           |
| zenburn-theme-20231120.2002                  |


Alright, there are precisely 402 packages. Some of them are necessary others were added in due course to add some specific functionality, which probably missing from the basic offering. Oh, importantly, I have failed to clean up a few of the old rugs, need to find time to do that.

Likewise, my other often-used editor is Vim2, and it has a similar effect to the above one.

Here is the package/capabilities included for the sake of enhancement 🙂

ls -al ~/.vim/bundle | gawk '{ print $9 }' | grep -v .vundle
#+RESULTS:
|                                         |
| .                                       |
| ..                                      |
| AutoComplPop                            |
| Vundle.vim                              |
| ack.vim                                 |
| auto-pairs                              |
| bash-support.vim                        |
| calendar.vim                            |
| command-t                               |
| commentary                              |
| cscope_quickfix.vim                     |
| cscope_quickfix.vim.2022-02-26_12:15:38 |
| fileselect                              |
| fzf                                     |
| fzf.vim                                 |
| i3config.vim                            |
| open-browser.vim                        |
| org.vim                                 |
| restore_view.vim                        |
| scratch.vim                             |
| setcolors.vim                           |
| sudo.vim                                |
| surround                                |
| tabular                                 |
| tagbar                                  |
| undotree                                |
| unimpaired                              |
| urlview.vim                             |
| vifm.vim                                |
| vim-LanguageTool                        |
| vim-airline                             |
| vim-airline-themes                      |
| vim-bookmarks                           |
| vim-colors-solarized                    |
| vim-colorschemes                        |
| vim-commentary                          |
| vim-exchange                            |
| vim-floaterm                            |
| vim-gnupg                               |
| vim-latex                               |
| vim-live-latex-preview                  |
| vim-macrobatics                         |
| vim-markdown                            |
| vim-mergetool                           |
| vim-shortcut                            |
| vim-startify                            |
| vim-startuptime                         |
| vim-surround                            |
| vim-taskwarrior                         |
| vim-terminator                          |
| vim-titlecase                           |
| vim-unimpaired                          |
| vim-winmanip                            |
| vimagit                                 |
| vimwiki                                 |

Now, if you can count, it has 56 plugins to get with it. You must be screaming that a whooping number and it certainly slows down the damn thing. Yes, it is and I am in the process eliminating of one after another once I figure out, how to achieve that functionality in the normal way. That takes a lot of time to investigate and implement.

Now, if I measure (with the available capability) the startup time, it shows like this :

Emacs startup time by Esup3

Total User Startup Time: 0.891sec     Total Number of GC Pauses: 40     Total GC Time: 0.552sec

Vim startup time by vim-startuptime4

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.045  000.045: --- VIM STARTING ---
000.664  000.619: Allocated generic buffers
000.849  000.185: locale set
000.874  000.025: window checked
003.145  002.271: inits 1
003.307  000.162: parsing arguments
003.311  000.004: expanding arguments
003.422  000.111: shell init
005.727  002.305: Termcap init
005.785  000.058: inits 2
006.414  000.629: init highlight
018.887  008.160  008.160: sourcing /usr/share/vim/vim90/colors/lists/default.vim
019.799  010.035  001.875: sourcing /usr/share/vim/vim90/syntax/syncolor.vim
020.458  011.167  001.132: sourcing /usr/share/vim/vim90/syntax/synload.vim
084.334  000.331  000.331: sourcing /usr/share/vim/vimfiles/ftdetect/cmake.vim
086.198  001.720  001.720: sourcing /usr/share/vim/vimfiles/ftdetect/gentoo.vim
086.407  000.067  000.067: sourcing /usr/share/vim/vimfiles/ftdetect/llvm-lit.vim
086.577  000.053  000.053: sourcing /usr/share/vim/vimfiles/ftdetect/llvm.vim
086.899  000.214  000.214: sourcing /usr/share/vim/vimfiles/ftdetect/meson.vim
087.063  000.052  000.052: sourcing /usr/share/vim/vimfiles/ftdetect/mir.vim
087.244  000.073  000.073: sourcing /usr/share/vim/vimfiles/ftdetect/ninja.vim
087.402  000.049  000.049: sourcing /usr/share/vim/vimfiles/ftdetect/tablegen.vim
087.588  000.076  000.076: sourcing /usr/share/vim/vimfiles/ftdetect/vifm-rename.vim
087.834  000.135  000.135: sourcing /usr/share/vim/vimfiles/ftdetect/vifm.vim
088.542  067.762  064.992: sourcing /usr/share/vim/vim90/filetype.vim
093.431  002.125  002.125: sourcing /usr/share/vim/vim90/autoload/dist/script.vim
098.955  008.094  005.969: sourcing /usr/share/vim/vim90/scripts.vim
099.834  091.093  004.070: sourcing /usr/share/vim/vim90/syntax/syntax.vim
100.458  000.087  000.087: sourcing /usr/share/vim/vim90/filetype.vim
101.121  000.383  000.383: sourcing /usr/share/vim/vim90/ftplugin.vim
103.035  096.427  004.864: sourcing /etc/vim/vimrc
107.433  003.239  003.239: sourcing /usr/share/vim/vim90/ftoff.vim
160.588  000.258  000.258: sourcing /usr/share/vim/vimfiles/ftdetect/cmake.vim
162.086  001.355  001.355: sourcing /usr/share/vim/vimfiles/ftdetect/gentoo.vim
162.271  000.061  000.061: sourcing /usr/share/vim/vimfiles/ftdetect/llvm-lit.vim
162.433  000.052  000.052: sourcing /usr/share/vim/vimfiles/ftdetect/llvm.vim
162.778  000.176  000.176: sourcing /usr/share/vim/vimfiles/ftdetect/meson.vim
162.944  000.053  000.053: sourcing /usr/share/vim/vimfiles/ftdetect/mir.vim
163.103  000.051  000.051: sourcing /usr/share/vim/vimfiles/ftdetect/ninja.vim
163.260  000.049  000.049: sourcing /usr/share/vim/vimfiles/ftdetect/tablegen.vim
163.430  000.063  000.063: sourcing /usr/share/vim/vimfiles/ftdetect/vifm-rename.vim
163.661  000.122  000.122: sourcing /usr/share/vim/vimfiles/ftdetect/vifm.vim
164.213  054.170  051.930: sourcing /usr/share/vim/vim90/filetype.vim
164.624  000.113  000.113: sourcing /usr/share/vim/vim90/ftplugin.vim
165.155  000.255  000.255: sourcing /usr/share/vim/vim90/indent.vim
169.473  003.027  003.027: sourcing /usr/share/vim/vim90/syntax/nosyntax.vim
171.447  001.209  001.209: sourcing /usr/share/vim/vim90/syntax/syncolor.vim
172.075  002.255  001.046: sourcing /usr/share/vim/vim90/syntax/synload.vim
172.774  007.387  002.105: sourcing /usr/share/vim/vim90/syntax/syntax.vim
174.931  001.181  001.181: sourcing /usr/share/vim/vim90/syntax/syncolor.vim
181.195  005.918  005.918: sourcing /usr/share/vim/vim90/colors/lists/default.vim
184.816  001.168  001.168: sourcing /usr/share/vim/vim90/syntax/syncolor.vim
186.794  001.187  001.187: sourcing /usr/share/vim/vim90/syntax/syncolor.vim
200.897  019.425  017.070: sourcing /home/bhaskar/.vim/colors/solarized.vim
202.779  001.239  001.239: sourcing /home/bhaskar/.vim/bundle/Vundle.vim/autoload/vundle.vim
204.590  001.286  001.286: sourcing /home/bhaskar/.vim/bundle/Vundle.vim/autoload/vundle/config.vim
256.456  000.103  000.103: sourcing /usr/share/vim/vim90/filetype.vim
259.708  000.122  000.122: sourcing /usr/share/vim/vim90/ftplugin.vim
262.862  000.076  000.076: sourcing /usr/share/vim/vim90/indent.vim
266.179  000.083  000.083: sourcing /usr/share/vim/vim90/filetype.vim
269.428  000.101  000.101: sourcing /usr/share/vim/vim90/ftplugin.vim
272.708  001.564  001.564: sourcing /home/bhaskar/.vim/bundle/vim-shortcut/plugin/shortcut.vim
328.697  000.111  000.111: sourcing /home/bhaskar/.cache/calendar.vim/credentials.vim
383.577  000.804  000.804: sourcing /home/bhaskar/.vim/bundle/setcolors.vim
469.561  003.215  003.215: sourcing /home/bhaskar/.vim/bundle/cscope_quickfix.vim
474.522  000.528  000.528: sourcing /usr/share/vim/vim90/pack/dist/opt/cfilter/plugin/cfilter.vim
545.616  442.391  341.471: sourcing $HOME/.vimrc
545.684  000.452: sourcing vimrc file(s)
552.570  003.226  003.226: sourcing /home/bhaskar/.vim/plugin/dwm.vim
553.069  000.328  000.328: sourcing /home/bhaskar/.vim/plugin/fileselect.vim
553.695  000.505  000.505: sourcing /home/bhaskar/.vim/plugin/sshknownhost.vim
557.231  000.815  000.815: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/init.vim
560.924  000.729  000.729: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/parts.vim
573.579  001.500  001.500: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/util.vim
574.214  019.966  016.922: sourcing /home/bhaskar/.vim/bundle/vim-airline/plugin/airline.vim
574.994  000.223  000.223: sourcing /home/bhaskar/.vim/bundle/vim-airline-themes/plugin/airline-themes.vim
610.281  034.764  034.764: sourcing /home/bhaskar/.vim/bundle/vim-startuptime/plugin/startuptime.vim
612.897  000.216  000.216: sourcing /home/bhaskar/.vim/bundle/vifm.vim/autoload/vifm/globals.vim
616.139  005.051  004.835: sourcing /home/bhaskar/.vim/bundle/vifm.vim/plugin/vifm.vim
618.365  001.568  001.568: sourcing /home/bhaskar/.vim/bundle/vim-gnupg/plugin/gnupg.vim
626.801  002.194  002.194: sourcing /home/bhaskar/.vim/bundle/AutoComplPop/autoload/acp.vim
628.558  009.693  007.499: sourcing /home/bhaskar/.vim/bundle/AutoComplPop/plugin/acp.vim
639.065  009.881  009.881: sourcing /home/bhaskar/.vim/bundle/tagbar/plugin/tagbar.vim
641.643  001.438  001.438: sourcing /home/bhaskar/.vim/bundle/vim-latex/plugin/SyntaxFolds.vim
643.070  001.220  001.220: sourcing /home/bhaskar/.vim/bundle/vim-latex/plugin/filebrowser.vim
647.544  004.293  004.293: sourcing /home/bhaskar/.vim/bundle/vim-latex/plugin/imaps.vim
648.664  000.844  000.844: sourcing /home/bhaskar/.vim/bundle/vim-latex/plugin/remoteOpen.vim
650.099  000.546  000.546: sourcing /home/bhaskar/.vim/bundle/calendar.vim/plugin/calendar.vim
658.499  007.832  007.832: sourcing /home/bhaskar/.vim/bundle/fzf.vim/plugin/fzf.vim
664.504  005.429  005.429: sourcing /home/bhaskar/.vim/bundle/fzf/plugin/fzf.vim
665.361  000.081  000.081: sourcing /home/bhaskar/.vim/bundle/vim-shortcut/plugin/shortcut.vim
733.216  067.441  067.441: sourcing /home/bhaskar/.vim/bundle/vim-unimpaired/plugin/unimpaired.vim
735.309  001.363  001.363: sourcing /home/bhaskar/.vim/bundle/undotree/plugin/undotree.vim
737.418  001.658  001.658: sourcing /home/bhaskar/.vim/bundle/vim-commentary/plugin/commentary.vim
742.198  004.232  004.232: sourcing /home/bhaskar/.vim/bundle/vim-surround/plugin/surround.vim
743.825  000.941  000.941: sourcing /home/bhaskar/.vim/bundle/vim-titlecase/plugin/titlecase.vim
747.157  002.878  002.878: sourcing /home/bhaskar/.vim/bundle/vim-macrobatics/plugin/macrobatics.vim
748.615  000.935  000.935: sourcing /home/bhaskar/.vim/bundle/vim-startify/plugin/startify.vim
749.618  000.544  000.544: sourcing /home/bhaskar/.vim/bundle/urlview.vim/plugin/urlview.vim
751.348  001.256  001.256: sourcing /home/bhaskar/.vim/bundle/scratch.vim/plugin/scratch.vim
753.979  002.184  002.184: sourcing /home/bhaskar/.vim/bundle/open-browser.vim/plugin/openbrowser.vim
757.265  002.699  002.699: sourcing /home/bhaskar/.vim/bundle/command-t/plugin/command-t.vim
768.491  010.762  010.762: sourcing /home/bhaskar/.vim/bundle/bash-support.vim/plugin/bash-support.vim
770.830  001.682  001.682: sourcing /home/bhaskar/.vim/bundle/sudo.vim/plugin/sudo.vim
772.508  001.140  001.140: sourcing /home/bhaskar/.vim/bundle/vim-terminator/plugin/terminator.vim
775.070  001.135  001.135: sourcing /home/bhaskar/.vim/bundle/vimagit/plugin/../common/magit_common.vim
781.320  008.090  006.955: sourcing /home/bhaskar/.vim/bundle/vimagit/plugin/magit.vim
783.810  001.825  001.825: sourcing /home/bhaskar/.vim/bundle/tabular/plugin/Tabular.vim
787.673  003.045  003.045: sourcing /home/bhaskar/.vim/bundle/vim-floaterm/plugin/floaterm.vim
793.701  003.919  003.919: sourcing /home/bhaskar/.vim/pack/plugins/start/vimwiki/autoload/vimwiki/vars.vim
805.997  000.821  000.821: sourcing /home/bhaskar/.vim/pack/plugins/start/vimwiki/autoload/vimwiki/u.vim
830.932  042.788  038.048: sourcing /home/bhaskar/.vim/bundle/vimwiki/plugin/vimwiki.vim
832.191  000.557  000.557: sourcing /home/bhaskar/.vim/bundle/vim-LanguageTool/plugin/LanguageTool.vim
834.218  001.593  001.593: sourcing /home/bhaskar/.vim/bundle/restore_view.vim/plugin/restore_view.vim
838.182  003.482  003.482: sourcing /home/bhaskar/.vim/bundle/vim-winmanip/plugin/winmanip.vim
840.209  001.505  001.505: sourcing /home/bhaskar/.vim/bundle/ack.vim/plugin/ack.vim
844.381  003.696  003.696: sourcing /home/bhaskar/.vim/bundle/vim-exchange/plugin/exchange.vim
1027.886  183.913  183.913: sourcing /home/bhaskar/.vim/bundle/vim-taskwarrior/plugin/taskwarrior.vim
1033.093  004.417  004.417: sourcing /home/bhaskar/.vim/bundle/auto-pairs/plugin/auto-pairs.vim
1035.066  001.283  001.283: sourcing /home/bhaskar/.vim/bundle/vim-mergetool/plugin/mergetool.vim
1044.203  008.570  008.570: sourcing /home/bhaskar/.vim/bundle/vim-bookmarks/plugin/bookmark.vim
1045.999  000.663  000.663: sourcing /usr/share/vim/vimfiles/plugin/gentoo-common.vim
1048.775  000.090  000.090: sourcing /usr/share/vim/vimfiles/plugin/gentoo-common.vim
1053.446  007.257  007.167: sourcing /usr/share/vim/vimfiles/plugin/newebuild.vim
1056.404  000.092  000.092: sourcing /usr/share/vim/vimfiles/plugin/gentoo-common.vim
1060.081  006.363  006.271: sourcing /usr/share/vim/vimfiles/plugin/newglep.vim
1062.828  000.090  000.090: sourcing /usr/share/vim/vimfiles/plugin/gentoo-common.vim
1066.285  006.034  005.944: sourcing /usr/share/vim/vimfiles/plugin/newinitd.vim
1068.994  000.083  000.083: sourcing /usr/share/vim/vimfiles/plugin/gentoo-common.vim
1072.747  006.286  006.203: sourcing /usr/share/vim/vimfiles/plugin/newmetadata.vim
1075.100  000.475  000.475: sourcing /usr/share/vim/vim90/plugin/getscriptPlugin.vim
1077.266  002.009  002.009: sourcing /usr/share/vim/vim90/plugin/gzip.vim
1079.235  001.781  001.781: sourcing /usr/share/vim/vim90/plugin/logiPat.vim
1079.779  000.300  000.300: sourcing /usr/share/vim/vim90/plugin/manpager.vim
1081.498  001.569  001.569: sourcing /usr/share/vim/vim90/plugin/matchparen.vim
1086.932  005.231  005.231: sourcing /usr/share/vim/vim90/plugin/netrwPlugin.vim
1087.346  000.091  000.091: sourcing /usr/share/vim/vim90/plugin/rrhelper.vim
1087.723  000.198  000.198: sourcing /usr/share/vim/vim90/plugin/spellfile.vim
1089.357  001.461  001.461: sourcing /usr/share/vim/vim90/plugin/tarPlugin.vim
1090.773  001.150  001.150: sourcing /usr/share/vim/vim90/plugin/tohtml.vim
1092.228  001.272  001.272: sourcing /usr/share/vim/vim90/plugin/vimballPlugin.vim
1094.122  001.506  001.506: sourcing /usr/share/vim/vim90/plugin/zipPlugin.vim
1096.521  001.601  001.601: sourcing /usr/share/vim/vim90/pack/dist/opt/justify/plugin/justify.vim
1097.901  000.635  000.635: sourcing /usr/share/vim/vim90/pack/dist/opt/cfilter/plugin/cfilter.vim
1098.182  036.249: loading plugins
1099.534  000.114  000.114: sourcing /home/bhaskar/.vim/pack/plugins/start/org/ftdetect/org.vim
1100.178  000.099  000.099: sourcing /home/bhaskar/.vim/pack/plugins/start/vimwiki/plugin/vimwiki.vim
1100.777  002.382: loading packages
1109.017  001.963  001.963: sourcing /home/bhaskar/.vim/bundle/tabular/autoload/tabular.vim
1127.504  023.147  021.184: sourcing /home/bhaskar/.vim/bundle/tabular/after/plugin/TabularMaps.vim
1128.734  004.810: loading after plugins
1128.795  000.061: inits 3
1130.927  002.132: reading viminfo
1131.091  000.164: setting raw mode
1131.176  000.085: start termcap
1131.550  000.374: clearing screen
1135.886  002.635  002.635: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions.vim
1137.293  000.458  000.458: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/quickfix.vim
1139.390  001.481  001.481: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline.vim
1141.410  000.359  000.359: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/netrw.vim
1143.069  000.369  000.369: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/fzf.vim
1148.446  000.737  000.737: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/section.vim
1152.667  002.190  002.190: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/highlighter.vim
1154.964  008.850  005.923: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/term.vim
1157.076  000.269  000.269: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/commandt.vim
1158.199  000.216  000.216: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/undotree.vim
1159.786  000.584  000.584: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/vimagit.vim
1161.172  000.458  000.458: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/tagbar.vim
1162.530  000.257  000.257: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/bookmark.vim
1166.180  001.102  001.102: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/whitespace.vim
1169.049  000.443  000.443: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/po.vim
1170.701  000.725  000.725: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/wordcount.vim
1172.399  000.176  000.176: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/keymap.vim
1178.204  000.322  000.322: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/searchcount.vim
1213.431  000.277  000.277: sourcing /home/bhaskar/.vim/bundle/vim-taskwarrior/autoload/airline/extensions/taskwarrior.vim
1245.936  000.482  000.482: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/themes.vim
1248.702  004.443  003.961: sourcing /home/bhaskar/.vim/bundle/vim-airline-themes/autoload/airline/themes/base16_gruvbox_dark_hard.vim
1273.917  003.793  003.793: sourcing /home/bhaskar/.vim/bundle/vim-airline-themes/autoload/airline/themes/base16_gruvbox_dark_hard.vim
1465.058  001.186  001.186: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/builder.vim
1470.131  000.697  000.697: sourcing /home/bhaskar/.vim/bundle/vim-airline/autoload/airline/extensions/default.vim
1680.752  520.102: opening buffers
1691.410  010.658: BufEnter autocommands
1691.443  000.033: editing files in windows

Nope, not good. Needs serious trimming. But what is stopping me is that I have to find time and figure out what could be done to replace them with the native way. But by looking at the result I can spot a few for immediate removal because I am not using a few things that are still there and gobble up precious seconds.

Here is my Emacs client running in terminal mode i.e. with the -nw flags :

2024-04-18-171745_1920x1200_scrot.png

And here is what my Vim’s initial screen looks like :

2024-04-18-170755_1920x1200_scrot.png

Linux Viewing Man Pages Via Various Methods

So, viewing Linux Manual Pages is an integral activity that we often perform. But the important part is, we want it to get access from anywhere in the system. Simply, because of convenience to find out the exact details we are sought after.

In this post, I am going to show you various ways I personally access those man pages in my system. You might like it and if any of them suits your workflow might adapt it.

Accessing Linux Manual Pages Via Window Manager And Associated Tools

This is a biggie, and it needs more than one tool to accomplish the job. In crux, the integration helps to see manual pages via dmenu and shows up with a pdf viewer.

First I needed to curate a little script and I wrote it in bash1 (you can use whatever language you are comfortable with) and it is essentially a borrowed idea, so I adopted it.

Here is the little script :

#!/usr/bin/env bash

man -k .  | dmenu -l 30 | gawk '{print $1}' | xargs -r man -Tpdf | zathura - &

You see, I am sitting on I3 Window Manager2 and using dmenu3 as a command launcher, and then using all the basic UNIX commands, and finally using zathura4 as pdf viewer.

I have a bind in the window Maker configuration file(i.e. i3 config file) like this :

bhaskar_13:13:50_Fri Apr 12: :~>grep manual .ithreeconfig | head -2
# Open manual page as pdf
bindsym $mod+grave exec manual_view_in_pdf

The grave sign is on the same key where the tilde sign is i.e. from the top second-row leftmost key on the QWERTY keyboard.

And I don’t have to stretch much of my finger to use this key bind. YMMV.

From The Terminal aka Command Line And With The Help Of FZF5

I have a small snippet in my .bashrc file which allows me to search and see the Linux Manual page on the terminal itself.

Here is the code :

bhaskar_13:19:36_Fri Apr 12: :~>declare -f tm
tm ()
{
    local man_page;
    man_page=$(man -k . | sort | fzf --prompt='Man Pages> ' --preview='echo {} | awk "{print \$1}" | xargs man' --preview-window=right:60%:wrap);
    man "$(echo "$man_page" | awk '{print $1}')"
}

See! Nothing much. When I invoke tm on the command line, it shows like this :

2024-04-12-132104_1920x1200_scrot.png

Accessing Linux Manual Pages Via Vim6

This is again a borrowed idea and because I use Vim extensively, so thought to integrate with it for benefit.

Here is what I have in my .vimrc

bhaskar_13:23:26_Fri Apr 12: :~>grep Man .vimrc
" Man pages with fzf
command! -nargs=? Man call fzf#run(fzf#wrap({'source': 'man -k -s 1 '.shellescape(<q-args>).' | cut -d " " -f 1', 'sink': 'tab Man', 'options': ['--preview', 'MANPAGER=bat MANWIDTH='.(&columns/2-4).' man {}']}))
nnoremap <Leader>m :Man<CR>

As you can see, I have a key bind ;a, and if I invoke that inside Vim, then it will show like this:

2024-04-12-132809_1920x1200_scrot.png

Accessing Linux Manual Pages Via Emacs7

When I am inside the Emacs environment, then I try to use the wonderful facilities provided by that environment to enhance productivity. Emacs has a way of showing Linux manual pages, and once invoked via key cord or M-x prompt, it shows like this :

2024-04-12-133405_1920x1200_scrot.png

Linux Distributions Download And Verification Automation

Alright, Linux Fanatics never stops trying various things aka exploring, especially when they are young and exuberant. We all have been trapped in that vicious activity for years just for perfection. Alas! Despite our endless hours search and doing various crazy things, we are just not settling on a particular thing.

Distro hopping is considered very normal and in fact, a desired activity seen by other fellas in the field of the same. Not doing so, considered that serious limitation of your intellect and capabilities and is sometimes frowned upon. So, as a result, we all dive in with aplomb and do as many crazy things as possible. But that does not end there, we go one step further and claim our specific work is a kinda standard and others should follow.

This is a vibe and not necessarily told explicitly otherwise. Any enthusiasts with little sense get it within a few days of foray into this bandwagon. And it doesn’t take too much to be part of it. Especially the shortcoming of our knowledge about the internals initially makes it even more possible. The suggestions you are getting everywhere, on all the online places, namely, forums and site specifics to support provide you with weird suggestions to try out. And our brains are so triggered by those suggestions and we do not waste time to head on to try all that said. Such a force.

Likewise, the beauty of open-source software is that your problem no longer stays unresolved for too long. How? Someone like you might encounter it and find a solution to that problem and post it online somewhere so others get the benefit of that finding. Such a boon. But, wait, there are lots of presumptions regarding that. It is not always the case. Sometimes, suggestions are way off and done in assumption and importantly in very different situations and environments. People get stumped by that very often with a late realization. The temptation to find the solution is so high that people ignore the basics of understanding and have an unfathomable inclination to adopt whatever is thrown at them.

You learn some by reading those offerings and loathe some. Not to mention, in between creeps devilish idea to put on the sword’s edge to get the sadistic pleasure of your unawareness. But, don’t worry you will learn fast, how to avoid those evils. They follow some patterns and it is very vivid despite their motivated effort.

Moreover, every damn Linux distribution offers some flavor to make themselves different from the others. Sometimes, it is a business policy, and others are driven by some sort of inexplicable ethos for design. Also, people offering those distributions came from different backgrounds and understandings, so baked that into their loved stuff. As a result, we as an end user get various flavors to try on.

People start to play with them having installed in the physical partitions( many many moons ago, and I belong from that era), and then comes virtualization, which makes things easier to try something and not touch the base system. Plus, you do not have to wrongly erase in the process the wrong drive having different things.

Now, why do people try that I have said it at the outset of this article. But there are more, namely, people get bored with one thing, different looks and feel, and missing capabilities on one and finding it on the other. I have personally tried at least 30 of various offerings(nope, I am not ashamed of that) before setting on finally a few selective ones. It is a process that takes years to neck deep in the ecosystem to get along and find out the pros and cons(like every other thing in life). But, the realization kicks in with various factors come into play. In your pursuit of finding the silver bullet (that’s taken out Fredrick. P. Brooks, Jr’s paper by the same name)conclude that there is NO silver bullet to all our desired Linux distributions. There never will be.

The availability of preferred software packages is not consistent and sometimes does not even ship. The awkward naming scheme of the same packages for different distributions confused end users and forced them to search more. Nope, compiling from is NOT the norm, until you are forced, desperate, and capable of resolving the glitch by looking or it in the code or asking various places on the internet, many people I have seen, don’t ask questions and they are stuck with their fallacy. They thought asking questions publicly was a matter of shame and not good for their ego and status. So, they suffer the most by being dumb and spending a hell of a time doing things they are not supposed to do.

We all know that Eric. S. Raymond wrote a template1, that should be the basis of asking questions in places where you seek help. Not so surprisingly, the majority of the people initially do not read it or find it and know it, so make fault by putting the way they feel it helps them to answer their query. Not the way it is. So, eventually, someone wise enough to point that document to them insists on reading for their betterment. Those who do, have an edge over others in the future of getting help.

To make things easy for people with an unavoidable need to hop between various distributions, I have written an ordinary script(inspired by some other people’s already-written ideas) to download and verify the chosen distribution. Some of the stuff might need some careful updates because it is been a while since I haven’t updated the script. I am expecting the user will be curious enough to find the missing part and update accordingly.

Here is the script entirety for your perusal 🙂

#!/usr/bin/env bash
# Download and verify Linux distribution installers/ISO images
# Modified version of https://github.com/nodiscc/distrib-dl

set -o errexit
set -o nounset
set -o pipefail
usage="$(basename $0) DISTRIBUTION1 [DISTRIBUTION2 DISTRIBUTION3 ...]"

##############################
# Configuration

### GENTOO (LIVE DVD)
# https://www.gentoo.org/downloads/signatures/
gentoo_release="20160704"
gentoo_image="livedvd-x86-amd64-32ul"
gentoo_gpg2_fingerprint="D99EAC7379A850BCE47DA5F29E6438C817072058"
### DEBIAN
# one of: amd64-i386 amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel multi-arch powerpc s390 s390x source sparc
debian_architecture="amd64"
debian_version="10.3.0"
debian_gpg2_fingerprint="DF9B9C49EAA9298432589D76DA87E80D6294BE9B"
### FREEBSD
freebsd_version="12.0"
### SLACKWARE CURRENT
slack_release="slackware-current-mini-install"
slack_md5sum="8c48b807e1313c0431166786a6296a4f"
### ARCH LINUX
arch_release="2020.04.01-x86_64"
arch_image="archlinux-20202.04.01-x86_64"
arch_gpg2_fingerprint="0E8B644079F599DFC1DDC3973348882F6AC6A4C2"
#change the below date manually
rel_date="2020.04.01"
### OpenSUSE TUMBLEWEED
opensuse_release="tumbleweed"
opensuse_image="openSUSE-Tumbleweed-DVD-x86_64-Current"
opensuse_gpg2_fingerprint="0x22C07BA534178CD02EFE22AAB88B2FD43DBDC284"
### UBUNTU
ubuntu_codename="eoan"
ubuntu_release="19.10"
ubuntu_image="ubuntu-${ubuntu_release}-desktop-amd64"
ubuntu_gpg2_fingerprint1="46181433FBB75451"
ubuntu_gpg2_fingerprint2="D94AA3F0EFE21092"
### VOID Linux
voidlinux_image="void-live-x86_64-20191109"
voidlinux_gpg2_fingerprint="8DEBDA68B48282A4"
### NIXOS
nixos_release="nixos-graphical-19.09.1269.09f5f3a810c-x86_64-linux"
nixos_gpg2_fingerprint1="0xFE918C3A98C1030F"
nixos_gpg2_fingerprint2="0x846FDED7792617B4"
nixos_gpg2_fingerprint3="0xC2FFBCAFD2C24246"
### FEDORA
fedora_image="Fedora-Server-netinst-x86_64-32-1.6.iso"
fedora_gpg2_fingerprint="97A1AE57C3A2372CCA3A4ABA6C13026D12C944D0"
### SOLUS
solus_image="Solus-4.2-Budgie.iso"
solus_gpg2_fingerprint="96B4A0291094A86A2B7E3367DD672FE9A2BE5892"
### CLEAR LINUX
clearlinux_image="clear-32910-live-desktop.iso"
#clearlinux_gpg2_fingerprint=""
############################

# abort on errors
set -o errexit

download_dir="$PWD"
usage="$(basename $0)  DISTRIBUTION1 [DISTRIBUTION2 DISTRIBUTION3]"

#Options:
#-c        only check that the url returns 200, don't download anything"

distros="Available distributions:
                         gentoo
                         debian
                         freebsd
                         slackware_current
                         archlinux
                         opensuse_tumbleweed
                         ubuntu
                         voidlinux
                         nixos
                         fedora
                         solus
                         clearlinux"



if [[ $# == 0 ]];then
        echo $usage
        echo $distros
fi


############################
download_gentoo() {
    # https://www.gentoo.org/downloads/mirrors/
    gentoo_base_url="https://mirror.bytemark.co.uk/gentoo/releases/amd64/${gentoo_release}/"
    gentoo_iso_filename="${gentoo_image}-${gentoo_release}.iso"
    gentoo_sums_filename="${gentoo_iso_filename}.DIGESTS.asc"
    gentoo_gpg2keyring_filename="${gentoo_iso_filename}.DIGESTS.sig"
    if [[ ! -d "$download_dir/gentoo/" ]]; then mkdir -p "$download_dir/gentoo/"; fi
    echo "[distrib-dl] INFO: Downloading gentoo keyring, checksums and signature..."
    gpg2 --keyserver hkps://keys.gentoo.org --recv-keys "$gentoo_gpg2_fingerprint"
    wget -N -nv --show-progress -P "$download_dir/gentoo/" "${gentoo_base_url}${gentoo_gpg2keyring_filename}"
    wget -N -nv --show-progress -P "$download_dir/gentoo/" "${gentoo_base_url}${gentoo_sums_filename}"
    gpg2 --verify "gentoo/${gentoo_sums_filename}"
    echo "[distrib-dl] INFO: Downloading Gentoo Live ISO image..."
    wget --continue -N -nv --show-progress -P "$download_dir/gentoo/" "${gentoo_base_url}/${gentoo_iso_filename}"
    echo "[distrib-dl] INFO: Verifying Gentoo Live ISO image integrity..."
    cd "$download_dir/gentoo/" && sha512sum --ignore-missing -c <(cat ${gentoo_sums_filename}) && cd -
}
download_debian() {
    debian_base_url="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd"
    debian_iso_filename="debian-${debian_version}-${debian_architecture}-netinst.iso"
    debian_sums_url="${debian_base_url}/SHA512SUMS"
    debian_sums_sign_url="${debian_base_url}/SHA512SUMS.sign"
    if [[ ! -d "$download_dir/debian/" ]]; then mkdir -p "$download_dir/debian/"; fi
    echo "Downloading Debian keyring, checksums and signature..."
     gpg2 --keyserver hkps://keyring.debian.org  --recv-keys "$debian_gpg2_fingerprint"
    # shellcheck disable=SC2086
    wget -N -nv --show-progress -P "$download_dir/debian/" "$debian_sums_url"
    # shellcheck disable=SC2086
    wget -N -nv  --show-progress -P "$download_dir/debian/" "$debian_sums_sign_url"
    echo "Verifying Debian signature..."
    gpg2 --verify "$download_dir/debian/SHA512SUMS.sign" "$download_dir/debian/SHA512SUMS"
    echo "Downloading Debian ISO image..."
    # shellcheck disable=SC2086
    wget --continue -N -nv --show-progress -P "$download_dir/debian/" "$debian_base_url/$debian_iso_filename"
    echo "Verifying Debian ISO image integrity..."
    cd "$download_dir/debian/" && sha512sum -c <(cat SHA512SUMS) && cd -
}
download_freebsd() {
    freebsd_base_url="https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/${freebsd_version}"
    freebsd_iso_firlename="FreeBSD-${freebsd_version}-RELEASE-amd64-memstick.img"
    freebsd_sums_filename="CHECKSUM.SHA512-FreeBSD-${freebsd_version}-RELEASE-amd64.asc"
    freebsd_sums_url="https://www.freebsd.org/releases/${freebsd_version}R/${freebsd_sums_filename}"
    freebsd_gpg2keyring_url="https://www.freebsd.org/doc/pgpkeyring.txt"
    if [[ ! -d "$download_dir/freebsd/" ]]; then mkdir "$download_dir/freebsd/"; fi
    echo "[distrib-dl] INFO: Downloading freebsd keyring, checksums and signature..."
    # shellcheck disable=SC2086
    wget $wget_opts --timestamping --no-verbose --show-progress -P "$download_dir/freebsd/" "$freebsd_gpg2keyring_url"
    # shellcheck disable=SC2086
    wget $wget_opts --timestamping --no-verbose --show-progress  -P "$download_dir/freebsd/" "$freebsd_sums_url"
    gpg2 --verify "freebsd/$freebsd_sums_filename"
    echo "[distrib-dl] INFO: Downloading freebsd ISO image..."
    # shellcheck disable=SC2086
    wget $wget_opts --continue --timestamping --no-verbose --show-progress -P "$download_dir/freebsd/" "$freebsd_base_url/$freebsd_iso_filename"
    echo "Verifying freebsd ISO image integrity..."
    cd "$download_dir/freebsd/" && sha512sum --ignore-missing -c <(cat ${freebsd_sums_filename}) && cd -
}
download_slackware_current() {
        # https://slackware.uk/people/alien-current-iso/slackware-current-iso/
        slack_base_url="https://slackware.uk/people/alien-current-iso/slackware-current-iso/"
        slack_iso_filename="${slack_release}.iso"
        slack_sums_filename="MD5SUM"
        slack_sums_url="https://slackware.uk/people/alien-current-iso/slackware-current-iso/${slack_sums_filename}"
        if [[ ! -d "$download_dir/slackware_current/" ]]; then mkdir -p "$download_dir/slackware_current/"; fi
        wget -N -nv --show-progress -P "$download_dir/slackware_current" "${slack_base_url}${slack_sums_filename}"
        echo "Downloading Slackware-current Linux ISO image..."
        wget --continue -N -nv --show-progress -P "$download_dir/slackware_current/" "${slack_base_url}${slack_iso_filename}"
        echo "Verifying Slackware-current ISO image integrity..."
        cd "$download_dir/slackware_current/" && md5sum -c <(cat ${slack_sums_filename}) && cd -
}
download_archlinux() {
        # https://www.archlinux.org/downloads
        arch_base_url="http://mirror.rackspace.com/archlinux/iso/${rel_date}/"
        arch_iso_filename="archlinux-${arch_release}.iso"
        arch_sums_filename="sha1sums.txt"
        arch_gpg2keyring_filename="archlinux-${arch_release}.iso.sig"
        if [[ ! -d "$download_dir/archlinux/" ]]; then mkdir -p "$download_dir/archlinux/"; fi
        echo "Downloading arch keyring, checksums and signature..."
        gpg2  --recv-keys "$arch_gpg2_fingerprint"
        wget -N -nv --show-progress -P "$download_dir/archlinux/" "${arch_base_url}${arch_gpg2keyring_filename}"
        wget -N -nv --show-progress -P "$download_dir/archlinux/" "${arch_base_url}${arch_sums_filename}"
     #   gpg2 --verify  "archlinux/$arch_gpg2keyring_filename" "archlinux/${arch_sums_filename}"
        echo "Downloading Arch Linux ISO image..."
        wget --continue -N -nv --show-progress -P "$download_dir/archlinux/" "${arch_base_url}${arch_iso_filename}"
        echo "Verifying Arch Linux ISO image integrity..."
        cd "$download_dir/archlinux/" && sha1sum --ignore-missing -c <(cat ${arch_sums_filename}) && cd -
}
download_opensuse_tumbleweed() {
    # https://www.opensuse.org/#Tumbleweed
    opensuse_base_url="http://opensuse.mirrors.theom.nz/${opensuse_release}/iso/"
    opensuse_iso_filename="${opensuse_image}.iso"
    opensuse_sums_filename="${opensuse_iso_filename}.sha256"
    opensuse_asc_filename="${opensuse_sums_filename}.asc"
    if [[ ! -d "$download_dir/opensuse/" ]]; then mkdir -p "$download_dir/opensuse/"; fi
    echo "[distrib-dl] INFO: Downloading Opensuse Tumbleweed keyring, checksums and signature..."
    gpg2 --keyserver hkps://keyserver.ubuntu.com --recv-keys "$opensuse_gpg2_fingerprint"
    wget -N -nv --show-progress -P "$download_dir/opensuse/" "${opensuse_base_url}${opensuse_sums_filename}"
    wget -N -nv --show-progress -P "$download_dir/opensuse/" "${opensuse_base_url}${opensuse_asc_filename}"
    gpg2 --verify  "opensuse/${opensuse_asc_filename}" "opensuse/${opensuse_sums_filename}"
    echo "[distrib-dl] INFO: Downloading OpenSUSE Tumbleweed ISO image..."
    wget --continue -N -nv --show-progress -P "$download_dir/opensuse/" "${opensuse_base_url}${opensuse_iso_filename}"
    echo "[distrib-dl] INFO: Verifying OpenSUSE Tumbleweed ISO image integrity..."
    cd "$download_dir/opensuse/" && sha256sum --ignore-missing -c <(cat ${opensuse_sums_filename}) && cd -
}
download_ubuntu() {
        #http://releases.ubuntu.com/
        ubuntu_base_url="http://releases.ubuntu.com/${ubuntu_codename}/"
        ubuntu_iso_filename="${ubuntu_image}.iso"
        ubuntu_sums_filename="SHA256SUMS"
        ubuntu_gpg2keyring_filename="SHA256SUMS.gpg"
        if [[ ! -d "$download_dir/ubuntu/" ]]; then mkdir -p "$download_dir/ubuntu/"; fi
        echo "Downloading Ubuntu keyring, checksums and signature..."
        gpg2  --keyid-format long --keyserver hkps://keyserver.ubuntu.com --recv-keys "$ubuntu_gpg2_fingerprint1" "$ubuntu_gpg2_fingerprint2"
        wget -N -nv --show-progress -P "$download_dir/ubuntu/" "${ubuntu_base_url}${ubuntu_gpg2keyring_filename}"
        wget -N -nv --show-progress -P "$download_dir/ubuntu/" "${ubuntu_base_url}${ubuntu_sums_filename}"
        gpg2 --keyid-format long --verify "ubuntu/${ubuntu_gpg2keyring_filename}" "ubuntu/${ubuntu_sums_filename}"
        echo "Downloading Ubuntu Latest Desktop ISO image..."
        wget --continue -N -nv --show-progress -P "$download_dir/ubuntu/" "${ubuntu_base_url}/${ubuntu_iso_filename}"
        echo "Verifying Ubuntu Desktop ISO image integrity..."
        cd "$download_dir/ubuntu/" && sha256sum --ignore-missing -c <(cat ${ubuntu_sums_filename}) && cd -
}
download_voidlinux() {
        # https://alpha.de.repo.voidlinux.org/live/current/
        voidlinux_base_url="https://alpha.de.repo.voidlinux.org/live/current/"
        voidlinux_iso_filename="${voidlinux_image}.iso"
        voidlinux_sums_filename="sha256.txt"
        voidlinux_gpg2keyring_filename="sha256.sig"
        if [[ ! -d "$download_dir/voidlinux/" ]]; then mkdir -p "$download_dir/voidlinux/"; fi
        echo "Downloading VoidLinux keyring, checksums and signature..."
        gpg2  --keyid-format long --keyserver hkps://keyserver.ubuntu.com --recv-keys "$voidlinux_gpg2_fingerprint"
        wget -N -nv --show-progress -P "$download_dir/voidlinux/" "${voidlinux_base_url}${voidlinux_gpg2keyring_filename}"
        wget -N -nv --show-progress -P "$download_dir/voidlinux/" "${voidlinux_base_url}${voidlinux_sums_filename}"
        echo "Downloading VoidLinux ISO image..."
        wget --continue -N -nv --show-progress -P "$download_dir/voidlinux/" "${voidlinux_base_url}${voidlinux_iso_filename}"
        echo "Verifying VoidLinux ISO image integrity..."
        cd "$download_dir/voidlinux/" && sha256sum --ignore-missing -c <(cat ${voidlinux_sums_filename}) && cd -
}
download_nixos() {
        #https://releases.nixos.org/nixos/19.09/nixos-19.09.1269.09f5f3a810c/nixos-graphical-19.09.1269.09f5f3a810c-x86_64-linux.iso
        nixos_base_url="https://releases.nixos.org/nixos/19.09/nixos-19.09.1269.09f5f3a810c/"
        nixos_iso_filename="${nixos_release}.iso"
        if [[ ! -d "$download_dir/nixos/" ]]; then mkdir -p "$download_dir/nixos/"; fi
        echo "Downloading NixOS security devs keys ..."
        gpg2  --keyid-format long --keyserver hkps://keyserver.ubuntu.com --recv-keys "$nixos_gpg2_fingerprint1" "$nixos_gpg2_fingerprint2" "$nixos_gpg2_fingerprint3"
        echo "Downloading NixOS Graphical install ISO image..."
        wget --continue -N -nv --show-progress -P "$download_dir/nixos/" "${nixos_base_url}${nixos_iso_filename}"
}
download_fedora() {
    #https://getfedora.org/en/workstation/download/
    fedora_base_url="https://fedora.mirrors.theom.nz/releases/32/Server/x86_64/iso/"
    fedora_iso_filename="${fedora_image}"
    fedora_sums_filename="Fedora-Server-32-1.6-x86_64-CHECKSUM"
    #fedora_gpg2keyring_filename="${fedora_iso_filename}.DIGESTS.sig"
    if [[ ! -d "$download_dir/fedora/" ]]; then mkdir -p "$download_dir/fedora/"; fi
    echo "[distrib-dl] INFO: Downloading fedora keyring, checksums and signature..."
    gpg2 --keyserver hkps://keyserver.ubuntu.com --recv-keys "$fedora_gpg2_fingerprint"
    #wget -N -nv --show-progress -P "$download_dir/fedora/" "${fedora_base_url}${fedora_gpg2keyring_filename}"
    wget -N -nv --show-progress -P "$download_dir/fedora/" "${fedora_base_url}${fedora_sums_filename}"
    gpg2 --verify "fedora/${fedora_sums_filename}"
    echo "[distrib-dl] INFO: Downloading Fedora Everything Netinstall ISO image..."
    wget --continue -N -nv --show-progress -P "$download_dir/fedora/" "${fedora_base_url}${fedora_iso_filename}"
    echo "[distrib-dl] INFO: Verifying Fedora Everything Netinstall ISO image integrity..."
    cd "$download_dir/fedora/" && sha256sum --ignore-missing -c <(cat ${fedora_sums_filename}) && cd -
}
download_solus() {
    # https://getsol.us/download/
    solus_base_url="https://mirrors.rit.edu/solus/images/4.2/"
    solus_iso_filename="${solus_image}"
    solus_sums_filename="${solus_image}.sha256sum"
    solus_gpg2keyring_filename="${solus_image}.sha256sum.sign"
    if [[ ! -d "$download_dir/solus/" ]]; then mkdir -p "$download_dir/solus/"; fi
    echo "[distrib-dl] INFO: Downloading Solus keyring, checksums and signature..."
    gpg2  --keyserver hkps://keyserver.ubuntu.com  --recv-keys "$solus_gpg2_fingerprint"
    wget -N -nv --show-progress -P "$download_dir/solus/" "${solus_base_url}${solus_gpg2keyring_filename}"
    wget -N -nv --show-progress -P "$download_dir/solus/" "${solus_base_url}${solus_sums_filename}"
    gpg2 --verify "solus/${solus_gpg2keyring_filename}" "solus/${solus_sums_filename}"
    echo "[distrib-dl] INFO: Downloading Solus Budgie Desktop ISO image..."
    wget --continue -N -nv --show-progress -P "$download_dir/solus/" "${solus_base_url}${solus_iso_filename}"
    echo "[distrib-dl] INFO: Verifying Solus Desktop ISO image integrity..."
    cd "$download_dir/solus/" && sha256sum --ignore-missing -c <(cat ${solus_sums_filename}) && cd -
}
download_clearlinux() {
    # https://clearlinux.org/downloads
    clearlinux_base_url="https://cdn.download.clearlinux.org/releases/32910/clear/"
    clearlinux_iso_filename="${clearlinux_image}"
    clearlinux_sums_filename="${clearlinux_iso_filename}-SHA512SUMS"
    clearlinux_gpg2keyring_filename="${clearlinux_iso_filename}-SHA512SUMS.sig"
    if [[ ! -d "$download_dir/clearlinux/" ]]; then mkdir -p "$download_dir/clearlinux/"; fi
    echo "[distrib-dl] INFO: Downloading ClearLinux keyring, checksums and signature..."
   # gpg2 --keyserver hkps://keyserver.ubuntu.com --recv-keys "$clearlinux_gpg2_fingerprint"
    wget -N -nv --show-progress -P "$download_dir/clearlinux/" "${clearlinux_base_url}${clearlinux_gpg2keyring_filename}"
    wget -N -nv --show-progress -P "$download_dir/clearlinux/" "${clearlinux_base_url}${clearlinux_sums_filename}"
   # gpg2 --verify "clearlinux/${clearlinux_gpg2keyring_filename}" "clearlinux/${clearlinux_sums_filename}"
    echo "[distrib-dl] INFO: Downloading ClearLinux ISO image..."
    wget --continue -N -nv --show-progress -P "$download_dir/clearlinux/" "${clearlinux_base_url}/${clearlinux_iso_filename}"
    echo "[distrib-dl] INFO: Verifying ClearLinux ISO image integrity..."
    cd "$download_dir/clearlinux/" && sha512sum --ignore-missing -c <(cat ${clearlinux_sums_filename}) && cd -
}

 _main() {
    wget_opts=""
    while getopts ":c" opt; do
        case $opt in
            c) wget_opts="--spider"; shift;;
            \?) echo "[distrib-dl] ERROR: invalid option -$OPTARG" >&2; exit 1;;
        esac
    done

    for distribution in "$@"; do
        if [[ "$distribution" == "gentoo" ]] ; then download_gentoo; fi
        if [[ "$distribution" == "debian" ]] ; then download_debian; fi
        if [[ "$distribution" == "freebsd" ]] ; then download_freebsd; fi
        if [[ "$distribution" == "--help" ]]; then echo "Usage: $usage"; exit 1; fi
        if [[ "$distribution" == "slackware_current" ]] ; then download_slackware_current; fi
        if [[ "$distribution" ==  "archlinux" ]] ; then download_archlinux; fi
        if [[ "$distribution" == "opensuse_tumbleweed" ]] ; then download_opensuse_tumbleweed; fi
        if [[ "$distribution" == "ubuntu" ]] ; then download_ubuntu; fi
        if [[ "$distribution" == "voidlinux" ]] ; then download_voidlinux; fi
        if [[ "$distribution" == "nixos" ]] ; then download_nixos; fi
        if [[ "$distribution" == "fedora" ]] ; then download_fedora; fi
        if [[ "$distribution" == "solus" ]] ; then download_solus; fi
        if [[ "$distribution" == "clearlinux" ]]; then download_clearlinux; fi
    done
}

#####################

_main "$@"

Spend some time with it to help you get your stuff easily. Here is an interaction with it :

2024-04-08-130000_1920x274_scrot.png

Linux Email Client Mutt Take Advantage Of Procmail And Fetchmail

Okay, I have written about Mutt before. Here I am going to specifically focus on two important tools to get integrated with it to help use this wonderful email client experience much better.

Procmail1

This is a wonderful utility to help filter messages. Here is my .procmailrc

PATH=/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/home/bhaskar/bin/

MAILDIR=$HOME/.maildir/

DEFAULT=$MAILDIR

LOGFILE=$MAILDIR/log

SHELL=/bin/bash

:0

!^Content-Type: message/

!^Content-Type: multipart/

!^Content-Type: application/pgp

{

:0 fBw

  • ^–—BEGIN PGP MESSAGE–—
  • ^–—END PGP MESSAGE–—
formail \

-i “Content-Type: application/pgp; format=text; x-action=encrypt”

:0 fBw

  • ^–—BEGIN PGP SIGNED MESSAGE–—
  • ^–—BEGIN PGP SIGNATURE–—
  • ^–—END PGP SIGNATURE–—
formail \

-i “Content-Type: application/pgp; format=text; x-action=sign” }

:0 h

  • ^Subject:[ ]+\/(|send)[ ]+key pub\>.*
mutt -s “Re: $MATCH” `formail -rtzxTo:` </home/bhaskar/gpg_pub_key/bhaskar_gpg.asc

:0

^From.*no-reply\@ted\.com

/dev/null

:0

^From.*naukrialerts\@naukri\.com

/dev/null

:0

^From.*noreply\@medium\.com

/dev/null

:0

^From.*info\@hirist\.com

/dev/null

:0

^From.*info\@naukri\.com

/dev/null

:0

^From.*alexk\@buddy\.works

/dev/null

:0

^From.*support\@brandyourself\.com

/dev/null

:0

^From.*tip-bot2\@linutronix\.de

tip-bot2

:0

^From.*notify\@protonmail\.ch

/dev/null

:0

^From.*informations\@hdfcbank\.net

/dev/null

:0hc
│ |grep “^To:\|^Subject:” > /run/user/1000/mail.notify-send; DISPLAY=:0 && export XAUTHORITY=/home/bhaskar/.Xauthority; notify-send –icon=/home/bhaskar/Pictures/neomutt.png “`cat /run/user/1000/mail.notify-send`”;

Basically to throw away useless junk mail permanently. You could write many other rules if you like to. Also, I have a key bind in my .muttrc to invoke it by hand from time to time.

macro index G "!fetchmail -a -m 'procmail -d %T'\r"

Fetchmail2

I have used it to fetch mail from the remote IMAP server. Here is my .fetchmailrc

#set daemon 120

set logfile /home/bhaskar/.fetchmail.log
     poll imap.your_mail_provider.com protocol imap
#poll imap.your_mail_provider.com protocol imap
          username "your_mail_address" password "your_password" is "bhaskar" here keep ssl;

          mda "/usr/bin/procmail -d %T"

Linux Extract Email Addresses and Web URLs From A Long Document

Alright! This is a tiny post about specifically two functions. You can either use it directly from the command line or embed those pieces into another script to do the job it is made for. I have used them in both forms. So, thought to share it with you people. 🙂

The file I am using to get the stuff from is quite big and filled with so much text. Refer to as a README.md file in the screenshots. I believe the similar file I have used in the video too.

Extracting Email Addresses From The Document

#!/usr/bin/env bash

filename=$1

egrep -o  "\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+.[a-zA-Z0-9.-]\b+" $filename

Hey, it is darn simple. In crux, it happens between the word boundary and the use of specific characters and symbols.

Example:

2024-03-30-172021_1916x114_scrot.png

Extracting The Web URLs From The Document

#!/usr/bin/env bash

filename=$1

if [[ $1 == "" ]];then
        echo you need to provide the filename.
        exit 1
        fi


sed -ne 's/.*\(http[^"]*\).*/\1/p'  < $filename

Ah, it is even easier, simple capture with some regex and replay it to print.

Example:

2024-03-30-172159_1906x222_scrot.png

Alternatively, You can take a peek at my YouTube Video regarding that.

Linux WordPress Blog Publish From Command Line

Well, I have been writing and posting my blogs on WordPress site using Emacs1. That was such a convenient and powerful package someone wrote and compelled me to adopt it and use it vigorously.

But depending on a single piece of software(after all, it is software, and every damn software is prone to bugs)is not a wise thing to do, when the other equally well(researched) option is good enough for backup and do the normal job in case the primary software misbehaves.

This kind of thing happens quite often with all the software, irrespective of whether it is open or closed source.

I was bugged(momentarily, read a few hours) by some sort of Emacs miscreants(it was probably all my fault than Emacs’s)and then that very moment I searched out for an alternative software that could do the same. And surprisingly, it takes very little time to find one. Someone bright enough has already written that piece for us. This is the true beauty of using open-source software, if someone encounters the same problem and finds a solution, they post it publicly for others to consume.

I have found a gem to publish a WordPress blog from the command line via a Perl script2.

Now, for my job to be easier, I have written a wrapper script to do the same. Here is the script entirety for your perusal :

#!/usr/bin/env bash

# This is a wrapper around a perl script to post woresspress blog from org file
# The original script can be found here : https://metacpan.org/dist/App-org2wp/view/script/org2wp

post_file=$1

_abort() {
if test "$post_file" == "";then
        echo You have not given the file containg post...so aborting..read the help below..
        echo
        $(command -v org2wp) -h
        exit 1
fi
}

# This is default behavior of the original script too,just making sure
_draft()  {
            if test $# -eq 1;then

                echo Posting as draft .....wait ...
                echo

                $(command -v org2wp) "$post_file"

                if test $? -eq 0;then

                        echo Posted the draft...checking at wordpress web interface..
                        echo
                        setsid -f $(command -v firefox) "https://wordpress.com/posts/drafts/unixbhaskar.wordpress.com" 2>&1 >/dev/null
                fi
           else

                 _abort
           fi
}

# This is how directly publish the post
_publish() {

        if test $# -ne 2;then

          _abort

       else
           echo Posting for publish directly .....
           echo

           $(command -v org2wp) --publish "$post_file"
        fi
}

# Calling up the routines
_main() {

      _draft "$@"

     _publish "$@"
}

_main "$@"

See! It is nothing much.

Now, you can watch that live on my YouTube Video

Linux nvme-cli Is To Aid NVME SSD Management

Well, modern-day computers come along with a new format, physical and logical, form called nvme1 way. It is no longer in spindle disk form. It is fast and occupies less space inside the chassis. So, the tool to manage this device is quite different than the way people used to handle and manage the disk previously.

nvme-cli2 is the package that ships with all the Linux distributions and might come in handy. So, go ahead and install it fast. You should be getting it from your chosen distribution’s main repository.

Now, I am going to show you some of the commands this package provides. Some of the commands need very careful steps to be performed or not to be used at all if you are not doing the prescribed task. In other words, some of the commands can prove fatal to play with, if there is no solid reason to invoke them.

nvme list

2024-03-26-095840_1920x143_scrot.png

nvme id-ctrl

2024-03-26-100040_775x344_scrot.png

nvme id-ns

2024-03-26-100318_803x271_scrot.png

nvme smart-log

2024-03-26-100512_1920x1200_scrot.png

nvme error-log

2024-03-26-100703_965x1087_scrot.png

I have stripped the screenshots for the sake of brevity and left them for the reader to use on their terminal to see the full output. Because many of the sub-commands produce quite large output, it is not wise to show here.

Let me give you the entire list from the actual document, where all the commands are mentioned:

nvme version    Display the current version
nvme list       Lists all the NVMe SSDs attached: name, serial number, size, LBA format, and serial
nvme id-ctrl    Discover information about NVMe controller and features it supports
nvme id-ns      Discover optimal namespace size, protection information, LBA size
nvme format     Secure erase the data on an SSD, format an LBA size or protection information for end-to-end data protection
nvme sanitize   Securely eliminate all data on device, cannot be stopped. Supports block, crypto, and overwrite
nvme smart-log  Health of the SSD (critical warning info), temperature, endurance, power on hours and error summary
nvme error-log  A log that contains information about errors encountered
nvme reset      Resets the NVMe controller
nvme create-ns  Create a namespace, can be used for overproviosning an SSD
nvme delete-ns  Remove a namespace
nvme device-self-test   Simple test for health of a drive, pass/fail
nvme fw-download, fw-commit     Download firmware to the drive, update the firmware on the drive
nvme help       Lists all the available commands

You can update the firmware of the SSD with the help of a subcommand.

Linux FFMPEG Interactive Cut Section Of Audio Video File

Well, I have shown my fondness for using FFmpeg1 before with other post2. I have also mentioned the topic of this post with an example in that post too. So, what’s new about that old topic? The new thing is that I have found a way to make the damn thing do it interactively with more precision. And it is not so complicated or long.

I am writing this with the hope that someone might find it useful for their workflow or usage.

It is just a bash script and the thing is here in entirety for your perusal:

#!/usr/bin/env bash

# Provide time in seconds


# if [[ $# -lt 4 ]];then

#       echo You are suppose to provide two parameters to this script
#       echo Times should be given in hh:mm:ss format
#       echo $(basename $0) -ss start_sec -i source_file end_sec modifed_file
#       exit 1
# fi

printf "Give the start time in HH:MM:SS format: %s"
read -r start_time

start_sec=$(echo "$start_time" | gawk -F: '{ print ($1 * 60) + ($2 * 60) + $3 }')

echo $start_sec

printf "Give the Souce file: %s"

read -r source_file

printf "Give the end time in HH:SS:MM format:  %s"
read -r end_time


end_sec=$(echo "$end_time" | gawk -F: '{ print ($1 * 60) + ($2 * 60) + $3 }')

echo $end_sec

printf "Give the modified file name: %s"
read -r modi_file

echo "ffmpeg -ss ${start_sec} -i ${source_file} -to ${end_sec} -c:a copy -c:v copy ${modi_file}.mp3"

printf "Is it look alright?[Y/N]: %s"
read -r res

if test "$res" == "Y";then

       sh -c "ffmpeg -ss ${start_sec} -i ${source_file} -to ${end_sec} -c:a copy -c:v copy ${modi_file}.mp3"

else
        printf "Something doesn't look right, fix it"

fi


See! Pretty ordinary. If you run it from the terminal it will prompt you for the start time and then source file, on which it will act upon and finally end time to round up the time range.

You might be interested to look at the YouTube Video about it.

Linux Consolidated Advance Materials

TL;DR It is a longish post, if you run out of patience, that is certainly not my fault. 🙂

Well, all of these, what I am going to dish out in this post is coming out of my long accumulated note files. I thought these might be useful to some people, who are looking for materials to study and apply. This is in no particular order, I just scanned through and found a few I can share at this moment. So, pay attention to your benefit. 🙂

Make file variables shorthand

Why? Delving with Linux sooner or later pushes you into a situation, where you are supposed to write some make file for your good. And here are some file-specific variable shorthand that might come in handy.

$@: the target filename.
$*: the target filename without the file extension.
$<: the first prerequisite filename.
$^: the filenames of all the prerequisites, separated by spaces, discard duplicates. 
$+: similar to $^, but includes duplicates. 
$?: the names of all prerequisites that are newer than the target, separated by spaces. 
$@: mute the command itself
$(info the message need to be printed)

Library linking breakage and fixing

This is a very common thing if you haven’t lived long with Linux. Why? It entails lots of reasons. So, knowing the reason and importantly fixing it might help in a good way.

You see the points extracted out of this: https://rosshemsley.co.uk/posts/linking

Points:

Dynamic or shared libraries are loaded up by your program at runtime. They contain lookup tables that map symbols to shared executable code. If you give someone a binary that links a dynamic library that they don’t already have, the OS will complain about missing libraries when they try to run it.

Dynamic or “shared” libraries have names that start with lib and finish with .so. Unless you’re on a Mac, where they end with .dylib.1

Dynamic libraries themselves can link to other dynamic libraries. These are known as transitive dependencies. All dependencies will need to be found to successfully run your binary.

If you want to move a binary from one machine (where it was compiled) to another, you’ll almost certainly find that at least some of the shared libraries needed by your binary are no longer found. This is usually the first sign of trouble…

Linux knows how to find libraries because it has a list of known locations for shared libraries in /etc/ld.so.conf. Each time you run ldconfig, the OS updates its cache of known libraries by going through directories in this file and reading the libraries it finds. OS X works differently… see ld and friends.

Use ldd (linux) or otool -L (OS X) to query your binary for the missing libraries. Beware that it is not safe to do this on a binary you suspect may be malicious 😞.

You can safely copy dynamic libraries from one machine to another. As long as the environments are similar enough…2 . In a perfect world (on linux), you could just copy the library you want to use into /usr/local/lib (the recommended place for unstable libraries) and then run ldconfig to make your OS reload its library cache.

Of course, on OS X things work totally differently. Dynamic libraries have an install name that contains the absolute path. This path is baked into your binary at compile time. You can use install_name_tool to change it. Good luck!

On linux, Adding libraries to /usr/local/lib makes them visible to everything, so you may want to copy your library somewhere else so that only your binary knows how to find it. One way to do this is using rpath…

You can set the rpath attribute of your binary to contain a directory hint for your OS to look in for libraries. This hint can be relative to your binary. This is especially useful if you always ship libraries in a relative directory to your binary. You can use @origin as a placeholder for the path of the binary itself, so a rpath of @origin/lib causes the OS to always look in <path to your binary>/lib for shared libraries at runtime. This can be used on both OS X and linux, and is one of the most useful tools for actually getting things working in practice.

If your OS isn’t finding a dynamic library that you know exists, you can try helping your OS by setting the environment variable LD_LIBRARY_PATH to the directory containing it – your OS will look there first before default system paths. Beware, this is considered bad practice, but it might unblock you in a pinch. OS X has DYLD_LIBRARY_PATH, which is similar, and also DYLD_FALLBACK_LIBRARY_PATH, which is similar, but different (sorry).

Dynamic libraries also have a thing called a soname, which is the name of the library, plus version information. You have seen this if you’ve seen libfoo.so.3.1 or similar. This allows us to use different versions of the same library on the same OS, and to make non backwards-compatible changes to libraries. The soname is also baked into the library itself.

Often, your OS will have multiple symlinks to a single library in the same directory, just with different paths containing version information, e.g. libfoo.so.3, libfoo.so.3.1. This is to allow programs to find compatible libraries with slightly different versions. Everything starts to get rather messy here… if you really need to get into the weeds, this article will help. You probably only need to understand this if you are distributing libraries to users and need to support compatibility across versions.

Of course, even if your binary only depends on a single symbol in a dynamic library, it must still link to that library. Now consider that the dependency itself may also link other unused transitive dependencies. Accidentally “catching a dependency” can cause your list of shared library dependencies to grow out of control, so that your simple hello world binary ends up depending on hundreds of megabytes of totally unused shared libraries 😞.

One solution to avoiding “dependency explosions” is to statically link symbols directly into your binary, so let’s start to look at static linking!

Static libraries (.a files) contain a symbol lookup table, similarly to dynamic libraries. However, they are much more dumb and also a total PITA to use correctly.

If you compile your binary and link in only static dependencies, you will end up with a static binary. This binary will not need to load any dependencies at runtime and is thus much easier to share with others!

People On The Internet will recommend that you do not not distribute static binaries, because it makes it hard to patch security flaws. With dynamic libraries, you just have to patch a single library e.g. libssl.so, instead of re-compiling everything on your machine that may have linked the broken library without your knowledge (i.e. everything).

People who build production systems at companies recommend static libraries because it’s way the hell easier to just deploy a single binary with zero dependencies that can basically run anywhere. No one cares about how big binaries are these days anyway.

Still, more people on the internet remind you that only one copy of a dynamic library is loaded into memory by the OS even when it is used by multiple processes, saving on memory pressure.

The static library people remind you that modern computers have plenty of memory and library size is hardly the thing killing us right now.

The OS X people point out that OS X strongly discourages the use of statically linked binaries.

Static libraries can’t declare any kind of library dependencies. This means it is your responsibility to ensure all symbols are baked correctly into your binary at link time – otherwise, your linker will fail. This can make linking static libraries painfully error-prone.

If you get symbol not found errors but literally swear that you linked every damn thing, you probably linked a static library and forgot a transitive dependency that is needed by it. This pretty much sucks as it’s basically impossible to figure out where that library comes from. Try having a guess by looking at the error messages. Or something?

Oh, and you must ensure that you link your static libraries in the correct order, otherwise you can still get symbol not found errors.

If you are starting to think it might be hard to keep track of static libraries, you are following along correctly. There are tools that can help you here, such as pkgconfig, CMake, autotools… or bazel. It’s quite easy to get going and achieve deterministic platform-independent static builds with no dynamic dependencies… Said no one ever 😓.

One classic way to screw up, is to compile a static library without using the -fPIC flag (for “position independent code”). If you do not do this, you will be able to use the static library in a binary, but you will not be able to link it into a dynamic library. This is especially frustrating if you were provided with a static library that was compiled without this flag and you can’t easily recompile it.

Beware that -fpic is not the same as -fPIC. Apparently, -fPIC always works but may result in a few nanoseconds of slowdown, or something. Probably you should use -fPIC and try not to think about it too much.

Your compiler toolchain (e.g. CMake) usually has a one-liner way to link a bunch of static libraries into a single dynamic library with no dependencies of its own. However, should you want to link a bunch of static libraries into another static library… well I’ve never successfully found a reliable way to do this 😞. Why do this you may ask? Mostly for cffi – when I want to build a single static library from C++ and then link it into e.g. a go binary.

Beware that your compiler/linker is not smart! Just because the header files declare a function and your linker manages to find symbols for it in your library, doesn’t mean that the function is remotely the same. You will discover this when you get undefined behavior at runtime.

Oh, and if the library you are linking was compiled with a #define switch set, but when you include the library’s headers, you do not set the define to the same value, welcome again to runtime undefined behavior land! This is the same problem as the one above, where the symbols end up being incompatible.

If you are trying to ship C++, another thing that can bite you is that the C++ standard library uses dynamic linking. This means that even the most basic hello world program cannot be distributed to others unless they have a compatible version of libstdc++. Very often you’ll end up compiling with a shiny new version of this library, only to find that your target is using an older, incompatible version.

One way to get around libstdc++ problems is to statically link it into your binary. However, if you create a static library that statically links libstdc++, and your library uses C++ types in its public interface… welcome again to undefined behavior land ☠️.

Another piece of classic advice is to statically link everything in your binary apart from core system libraries, such as glibc – which is basically a thin wrapper around syscalls. A practical goal I usually aim for is to statically link everything apart from libc and (preferably an older version of) libstdc++. This seems to be the safest approach.

Ultimately, my rule of thumb for building distributed systems is to statically link everything apart from libc and (an older version of) libstdc++. You can then put this library/binary into a Debian package, or an extremely lightweight Docker container that will run virtually anywhere. Setting up the static linking is a pain, but IMO worth the effort – the main benefits of dynamic libraries generally do not apply anymore when you are putting the binary in a container anyway.

Finally, for ultimate peace of mind, use a language that has a less insane build toolchain than C++. For example, Go builds everything statically by default and can link in both dynamic or static libraries if needed, using cargo. Rust also seems to work this way. Static binaries have started becoming fashionable

LD_LIBRARY_PATH Trouble and Solutions

It is very often caused by the misaligned or misplaced library in the system.

Pointer : https://www.hpc.dtu.dk/?page_id=1180

This little note is about one of the most “misused” environment variables on Unix systems: LD_LIBRARY_PATH . If used right, it can be very useful, but very often – not to say, most of the time – people apply it in the wrong way, and that is where they are calling for trouble. So, what does it do?

LD_LIBRARY_PATH tells the dynamic link loader (ld. so – this little program that starts all your applications) where to search for the dynamic shared libraries an application was linked against. Multiple directories can be listed, separated by a colon (:), and this list is then searched before the compiled-in search path(s), and the standard locations (typically /lib, /usr/lib, …).

This can be used for

testing new versions of a shared library against an already compiled application re-locating shared libraries, e.g. to preserve old versions creating a self-contained, relocatable(!) environment for larger applications, such that they do not depend on (changing) system libraries – many software vendors use that approach.

Sounds very useful, where is the problem?

Yes, it is useful – if you apply it in the way it was invented for, like the three cases above. However, very often it is used as a crutch to fix a problem that could have been avoided by other means (see below). It is even getting worse, if this crutch is applied globally into a user’s (or the system’s!) environment: applications compiled with those settings get dependent on this crutch – and if it is eventually taken away, they start to stumble (i.e. fail to run).

There are other implications as well:

Security: Remember that the directories specified in LD_LIBRARY_PATH get searched before(!) the standard locations? In that way, a nasty person could get your application to load a version of a shared library that contains malicious code! That’s one reason why setuid/setgid executables neglect that variable! Performance: The link loader has to search all the directories specified until it finds the directory where the shared library resides – for ALL shared libraries the application is linked against! This means a lot of system calls to open(), that will fail with “ENOENT (No such file or directory)”! If the path contains many directories, the number of failed calls will increase linearly, and you can tell that from the start-up time of the application. If some (or all) of the directories are in an NFS environment, the start-up time of your applications can really get long – and it can slow down the whole system! Inconsistency: This is the most common problem. LD_LIBRARY_PATH forces an application to load a shared library it wasn’t linked against, and that is quite likely not compatible with the original version. This can either be very obvious, i.e. the application crashes, or it can lead to wrong results if the picked-up library does not quite do what the original version would have done. Especially the latter is sometimes hard to debug.

How can I check which dynamic libraries are loaded?

There is the ldd command, that shows you which libraries are needed by a dynamically linked executable, e.g.

$ ldd /usr/bin/file
        linux-vdso.so.1 =>  (0x00007fff9646c000)
        libmagic.so.1 => /usr/lib64/libmagic.so.1 (0x00000030f9a00000)
        libz.so.1 => /lib64/libz.so.1 (0x00000030f8e00000)
        libc.so.6 => /lib64/libc.so.6 (0x00000030f8200000)
        /lib64/ld-linux-x86-64.so.2 (0x00000030f7a00000)

This is a ‘static’ view since ldd doesn’t resolve dependencies and libraries that will get loaded at runtime, e.g. by a library that depends on others. To get an overview of libraries loaded at runtime, you can use the pldd command:

$ ldd /bin/bash
        linux-vdso.so.1 =>  (0x00007ffff63ff000)
        libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003108a00000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00000030f8600000)
        libc.so.6 => /lib64/libc.so.6 (0x00000030f8200000)
        /lib64/ld-linux-x86-64.so.2 (0x00000030f7a00000)
$ pldd 24362
24362:  -bash
/lib64/ld-2.12.so
/lib64/libc-2.12.so
/lib64/libdl-2.12.so
/lib64/libtinfo.so.5.7
/usr/lib64/gconv/ISO8859-1.so
/lib64/libnss_files-2.12.so

As you can see, there are two more .so-files loaded at runtime, that weren’t on the ‘static’ list.

Note: pldd is originally a Solaris command, that usually is not available on Linux. However, there is a Perl-script available (and installed on our machines) that extracts this information from the /proc/<PID>/maps file. How to avoid those problems with LD_LIBRARY_PATH?

A very simplistic answer would be: “just don’t use LD_LIBRARY_PATH!” The more realistic answer is, “the less you use it, the better off you will be”.

Below is a list of ways how to avoid LD_LIBRARY_PATH, inspired by reference [1] below. The best solution is on the top, going down to the last resort.

If you compile your application(s) yourself, you can solve the problem by specifying the correct location of the shared libraries and telling the linker to add those to the runpath of your executable, specifying the path in the ‘-rpath’ linker option:

cc -o myprog obj1.o ... objn.o -Wl,-rpath=/path/to/lib \
   -L/path/to/lib -lmylib

The linker also reads the LD_RUN_PATH environment variable, if set, and thus you can specify more than one path in an easy way, without having to use the above linker option:

export LD_RUN_PATH=/path/to/lib1:/path/to/lib2:/path/to/lib3
cc -o myprog obj1.o ... objn.o -L/path/to/lib1 -lmylib1 \
   -L/path/to/lib2 -lmylib2 ...

In both cases, you can check with ldd, that your executable will find the right libraries at start-up (see above). If there is a ‘not found’ message in the ldd output, you have done something wrong and should review your Makefile and/or your LD_RUN_PATH settings. There are tools around, to fix/change the runpath in a binary executable, e.g. chrpath under Linux. The problem with this method is, that the space in the executable that contains this information (i.e. the string defining the path) cannot be extended, i.e. you cannot add additional information – only overwrite an existing path. Furthermore, if no runpath exists in the executable, there is no way to change it. Read the man page for chrpath for more information. If you can’t fix the executable, create a wrapper script that calls the executable with the right LD_LIBRARY_PATH setting. In that way, the setting gets exposed to this application, only – and the applications that get started by that. The latter can lead to the inconsistency problem above, though.

#!/bin/sh

LD_LIBRARY_PATH=/path/to/lib1:/path/to/lib2:/path/to/lib3

export LD_LIBRARY_PATH

exec /path/to/bin/myprog $@

Testing a LD_LIBRARY_PATH from the command line:

$ env LD_LIBRARY_PATH=/path/to/lib1:/path/to/lib2:/path/to/lib3 ./myprog

This sets LD_LIBRARY_PATH for this command only. Do NOT do:

$ export LD_LIBRARY_PATH=/path/to/lib1:/path/to/lib2:/path/to/lib3

$ ./myprog

since this will pollute the shell environment for all consecutive commands! Never put LD_LIBRARY_PATH in your login profiles! In that way you will expose all the applications you start to this – probably problematic – path!

Unfortunately, some ISVs ship software, that puts global LD_LIBRARY_PATH settings into the system profiles during the installation, or they ask the user to add those settings to their profiles. Just say no! Try you solve the problem by other means, e.g. by creating a wrapper script, or tell the vendor to fix this problem.

Glibc installation dependency

This is a crucial piece. Because a lot depends on this software.

Bash: sh
Binutils: ar, as, ld, ranlib, readelf
Diffutils: cmp
Fileutils: chmod, cp, install, ln, mknod, mv, mkdir, rm, touch
Gcc: cc, cc1, collect2, cpp, gcc
Grep: egrep, grep
Gzip: gzip
Make: make
Gawk: gawk
Sed: sed
Sh-utils: date, expr, hostname, pwd, uname
Texinfo: install-info, makeinfo
Textutils: cat, cut, sort, tr

Beginner’s guide to Linker

How pipes work in Linux

Toolchains

https://www.toolchains.net/

This is good enough to ponder for a few months.