<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Occasional dose of Srdjan Marjanovic]]></title><description><![CDATA[Thoughts, stories and ideas and grumblings of an average developer]]></description><link>https://blog.marjanovic.me/</link><image><url>https://blog.marjanovic.me/favicon.png</url><title>Occasional dose of Srdjan Marjanovic</title><link>https://blog.marjanovic.me/</link></image><generator>Ghost 4.18</generator><lastBuildDate>Mon, 12 Jan 2026 06:01:56 GMT</lastBuildDate><atom:link href="https://blog.marjanovic.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Linux offsite backups made easy]]></title><description><![CDATA[<p>Several of years ago I finally decided to invest time and money and build a home NAS. I had a bunch of photos from the DSLR scattered across numerous USB hard drives and decades worth of different &quot;backups&quot; so I wanted to centralize them. I did not want</p>]]></description><link>https://blog.marjanovic.me/linux-offsite-backups-made-easy/</link><guid isPermaLink="false">67c5b4a474540d00016af21d</guid><dc:creator><![CDATA[Srdjan Marjanovic ]]></dc:creator><pubDate>Mon, 03 Mar 2025 15:02:39 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1597852074816-d933c7d2b988?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fGhhcmQtZGlza3xlbnwwfHx8fDE3NDEwMTAwNzV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1597852074816-d933c7d2b988?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fGhhcmQtZGlza3xlbnwwfHx8fDE3NDEwMTAwNzV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Linux offsite backups made easy"><p>Several of years ago I finally decided to invest time and money and build a home NAS. I had a bunch of photos from the DSLR scattered across numerous USB hard drives and decades worth of different &quot;backups&quot; so I wanted to centralize them. I did not want to vendor-lock myself and pay for the Google or Microsoft storage plans or similar cloud backup solutions and besides that, I did not want to family photos to their servers. So the only option remaining was to build or buy a NAS server. As I&apos;m a web developer and ocassionally like to play with ops and tinker with linux servers, I decided to buy a cheap PC with good CPU, enough of RAM and throw in some WD RED drives. Although i have 2 x 4tb WD RED drives paired in RAID1 I still wanted to have some additional layer of redundancy. <br><br>So I bought another PC.... <br><br>Few months ago, I moved into my own office. And what better place to put the backup server in than that? </p><p>Now I was facing only 2 problems:</p><ol><li>servers being on different networks</li><li>which backup software to use</li></ol><h2 id="servers-being-on-different-networks">Servers being on different networks</h2><p>This is the problem because servers can not communicate directly when they are on behind different routers, behind a NAT and/or don&apos;t&apos; have a static IP. <br><br><strong>TAILSCALE TO THE RESCUE! </strong></p><p><a href="https://tailscale.com/">Tailscale</a> is kind of VPN but instead of on device acting as a central server, all devices registered are part of a network mesh. All devices will get a public IP so any device can connect to it over the internet without any need for port forwarding. Also, all devices can be pronounced as &quot;exit nodes&quot; towards the internet. By installing and setting up the tailscale on both servers, I was now able to make them &quot;see eachother&quot;. </p><h2 id="which-backup-software-to-use">Which backup software to use</h2><p>This was a tough one. I wanted to have incremental backups so I can backtrack files to some point in time but also in order to minimize the overhead space used. I also did not want to have some special backup file format from which I would have to restore the files, but rather just a plain and simple directory and file structure which I would be able to access from the backup server anytime without need for additional software or process. <br><br>At first I tried to set up urbackup.com for several days, but I struggled to do so for a number of reasons both on server (office backup server) and on client (home NAS server in this case) side. I looked at couple of different tools but none of them fit the descrption. I also tried to look for some existing <strong>rsync</strong> scripts that would fit my needs but didn&apos;t trust any of them. So I turned to ChatGPT... </p><p><strong>rsync TO THE RESCUE!</strong><br>I asked ChatGPT the following prompt:</p><blockquote>I have two linux servers. One at home which serves as home NAS and the other in the office, which should serve as a backup server for some files of the first one. Both servers are using tailscale. I want to have scheduled remote backups for some folders of the home server to the office server. I want to keep monthly backups, one for each of 12 months in a year, i want to keep weekly backup, one for each week in a month, where last weekly backup should become monthly backup for that month, and I also want to keep daily backup for each day in a week, where last backup of the week will also become weekly backup for that week. I dont want to keep full backups. I want to have one full backup and then only add differences to subsequent backups. I dont want files on the backup to be in some weird fileformat for which i would need some software to restore. I just want them to be plain old files and dirrectories organized in some logical manner so I can simply go in to a daily backup and access the whole file list as if it was a full backup.</blockquote><p>And this is what it&apos;s answer was:</p><blockquote>You can achieve this setup using <strong><code>rsync</code> with hard links</strong> to efficiently create incremental backups while keeping a fully browsable directory structure.</blockquote><p>After some trial and error we were able to make up with the following process:</p><p><strong>Step 1: install rsync on both servers:<br></strong><code>sudo apt update &amp;&amp; sudo apt install rsync</code></p><p><strong>Step 2: Set up SSH access </strong></p><ol><li>Generate SSH keys on your home NAS:<br><code>ssh-keygen -t ed25519</code></li><li>Copy the public key to the backup server:<br><code>ssh-copy-id user@office-server-tailscale-ip</code></li><li>Test passwordless SSH:<br><code>ssh user@office-server-tailscale-ip</code></li></ol><p><strong>Step 3. Create the Backup Script:</strong></p><p>We&apos;ll use <code>rsync</code> with <code>--link-dest</code> to create incremental backups while making them appear as full backups.</p><pre><code class="language-bash">#!/bin/bash

#Configuration - You will need to change the values below to suit your needs
SOURCE_DIR=&quot;/path/to/home/nas/folders/&quot;  # Directory to backup
BACKUP_BASE=&quot;/path/to/office/server/backups&quot;  # Base backup location on the office server
SSH_USER=&quot;home_server_user&quot;
REMOTE_HOST=&quot;office-server-tailscale-ip&quot;
BACKUP_USER=&quot;backup_server_user&quot;  # User who should own the backups on the remote server

# Get current date components
DAY=$(date +%A)           # Monday, Tuesday, ..., Sunday
DATE=$(date +%d-%m-%Y)    # Format: dd-mm-yyyy
WEEK=$(date +%U)          # Week number (00-53)
MONTH=$(date +%m)         # Month number (01-12)
YEAR=$(date +%Y)          # Year

# Define backup directories with date appended
DAILY_BACKUP=&quot;$BACKUP_BASE/daily/${DAY}_${DATE}&quot;
WEEKLY_BACKUP=&quot;$BACKUP_BASE/weekly/week_${WEEK}_${DATE}&quot;
MONTHLY_BACKUP=&quot;$BACKUP_BASE/monthly/${YEAR}-${MONTH}_${DATE}&quot;

# Find the previous daily backup (yesterday&#x2019;s backup)
PREVIOUS_BACKUP=$(ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &quot;ls -d $BACKUP_BASE/daily/* 2&gt;/dev/null | tail -n 1&quot;)

# Rsync options
RSYNC_OPTS=&quot;-a --delete --link-dest=$PREVIOUS_BACKUP&quot;

# Perform daily backup
rsync -e ssh $RSYNC_OPTS &quot;$SOURCE_DIR&quot; &quot;$SSH_USER@$REMOTE_HOST:$DAILY_BACKUP&quot;

# Set correct permissions and ownership on the backup server
ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &lt;&lt; EOF    
    chown -R $BACKUP_USER:$BACKUP_USER &quot;$DAILY_BACKUP&quot;    
    chmod -R u+rw,g+r,o+r &quot;$DAILY_BACKUP&quot;
EOF

# Every Sunday, create a weekly backup from the last daily backup

if [ &quot;$DAY&quot; == &quot;Sunday&quot; ]; then
    ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &quot;cp -al $DAILY_BACKUP $WEEKLY_BACKUP&quot;     ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &quot;chown -R $BACKUP_USER:$BACKUP_USER $WEEKLY_BACKUP &amp;&amp; chmod -R u+rw,g+r,o+r $WEEKLY_BACKUP&quot;
fi

# Check if today is the last day of the month
TOMORROW=$(date -d &quot;tomorrow&quot; +%d)
if [ &quot;$TOMORROW&quot; == &quot;01&quot; ]; then    
    ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &quot;cp -al $DAILY_BACKUP $MONTHLY_BACKUP&quot;     ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &quot;chown -R $BACKUP_USER:$BACKUP_USER $MONTHLY_BACKUP &amp;&amp; chmod -R u+rw,g+r,o+r $MONTHLY_BACKUP&quot;
fi

# Clean up old backups (keeping retention policy)
ssh &quot;$SSH_USER@$REMOTE_HOST&quot; &lt;&lt; EOF    
    # Keep only the last 7 daily backups    
    cd &quot;$BACKUP_BASE/daily&quot; &amp;&amp; ls -t | tail -n +8 | xargs -I {} rm -rf {}  
    # Keep only the last 5 weekly backups
    cd &quot;$BACKUP_BASE/weekly&quot; &amp;&amp; ls -t | tail -n +6 | xargs -I {} rm -rf {}
    # Keep only the last 12 monthly backups    
    cd &quot;$BACKUP_BASE/monthly&quot; &amp;&amp; ls -t | tail -n +13 | xargs -I {} rm -rf {}
EOF</code></pre><p><strong>Step 4. Create the destination directory structure on backup server</strong></p><pre><code class="language-bash">mkdir -p /path/to/office/server/backups/daily
mkdir -p /path/to/office/server/backups/weekly
mkdir -p /path/to/office/server/backups/monthly</code></pre><p><strong>Step 5: Automate with Cron</strong></p><p><code>crontab -e</code> on home server</p><p>add: <code>0 2 * * * /path/to/backup_script.sh</code></p><p>This will:</p><ul><li> Run the script <strong>every day at 2 AM</strong></li><li> Log output to <code>/var/log/backup.log</code> (useful for debugging)</li></ul><p><strong>Step 6: Verify Everything Works</strong></p><p>Test the script by running on home server:</p><p><code>bash /path/to/backup_script.sh</code></p><p>Then verify on the office backup server:</p><p><code>ls -l /path/to/office/server/backups/daily</code></p><h3 id="example-directory-structure-you-should-end-up-with">Example directory structure you should end up with</h3><pre><code>/backups/
&#x251C;&#x2500;&#x2500; daily/
&#x2502;   &#x251C;&#x2500;&#x2500; Monday_27-03-2025
&#x2502;   &#x251C;&#x2500;&#x2500; Tuesday_28-03-2025
&#x2502;   &#x251C;&#x2500;&#x2500; Wednesday_29-03-2025
&#x2502;   &#x251C;&#x2500;&#x2500; Thursday_30-03-2025
&#x2502;   &#x251C;&#x2500;&#x2500; Friday_31-03-2025  &lt;-- Last daily backup of the month
&#x2502;
&#x251C;&#x2500;&#x2500; weekly/
&#x2502;   &#x251C;&#x2500;&#x2500; week_10_10-03-2025
&#x2502;   &#x251C;&#x2500;&#x2500; week_11_17-03-2025
&#x2502;   &#x251C;&#x2500;&#x2500; week_12_24-03-2025
&#x2502;
&#x251C;&#x2500;&#x2500; monthly/
&#x2502;   &#x251C;&#x2500;&#x2500; 2025-01_31-01-2025  &lt;-- Last daily backup of January
&#x2502;   &#x251C;&#x2500;&#x2500; 2025-02_29-02-2025  &lt;-- Last daily backup of February (leap year)
&#x2502;   &#x251C;&#x2500;&#x2500; 2025-03_31-03-2025  &lt;-- Last daily backup of March</code></pre><p></p><p>Final thoughts:<br>&#x2705; rsync&apos;s <code>--delete</code> option will delete all the files on the backup server that are missing or have been deleted on the home server. You might want to remove this one, it&apos;s up to you<br>&#x2705; Ensures first backup is always a full backup (when no previous backup exists).<br>&#x2705; Uses incremental backups (<code>--link-dest</code>) only when a previous backup exists.<br>&#x2705; Automatically creates missing backup directories (<code>mkdir -p $DAILY_BACKUP</code>).<br>&#x2705; Prevents <code>rsync</code> from failing due to missing previous backup folders.<br>&#x2705; Maintains correct ownership (<code>chown user:user</code>) and permissions (<code>chmod -R u+rw,g+r,o+r</code>).</p>]]></content:encoded></item><item><title><![CDATA[Bye htop, hello bashtop]]></title><description><![CDATA[This article will show you how to install the bashtop, a contemporary htop replacement]]></description><link>https://blog.marjanovic.me/bye-htop-hello-bashtop/</link><guid isPermaLink="false">6166e347aa72900001903e85</guid><category><![CDATA[bashtop]]></category><category><![CDATA[elementaryos]]></category><category><![CDATA[linux]]></category><category><![CDATA[ubuntu]]></category><category><![CDATA[htop]]></category><dc:creator><![CDATA[Srdjan Marjanovic ]]></dc:creator><pubDate>Thu, 04 Jun 2020 22:48:38 GMT</pubDate><media:content url="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-03-01.20.32-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-03-01.20.32-1.png" alt="Bye htop, hello bashtop"><p>One of the first things I install when setting up a new Linux installation is <code>htop</code> - it&apos;s a defacto process manager for Linux command line. It has been around for quite some time, since 2004 to be exact. Recently, a modern, good looking replacement showed up - <a href="https://github.com/aristocratos/bashtop">Bashtop</a>. </p><h3 id="why-bashtop">Why Bashtop?</h3><p>First of all, <code>htop</code> is written in <strong>C programming language </strong>which means it has some dependencies needed &#xA0;to run graphical-like user interface in terminal. On the other hand, <code>bashtop</code> is entirely written as a <strong>single bash script</strong> so all you need to run it is bash shell and couple more utils which are pretty much standard to nowadays Linux distributions - <code>awk</code>, <code>sed</code>, GNU coreutils... </p><blockquote>Fun fact - the main motivation for this app to be written in bash script is that the developer wanted to learn bash scripting</blockquote><p>It provides much more information about hardware than <code>htop</code> CPU model, per-thread usage histogram, usage percentage and temperature. It also displays info about hard drives, network transfers etc. Also, it is super-easy to install and use, it looks amazing and refreshing. </p><p><strong>It also supports themes! It comes with both dark and light themes out of the box. FTW!</strong></p><p>These are some <strong>key features</strong> as listed on it&apos;s GitHub repo page:</p><ul><li>Easy to use, with a game inspired menu system.</li><li>Fast and &quot;mostly&quot; responsive UI with UP, DOWN keys process selection.</li><li>Function for showing detailed stats for selected process.</li><li>Ability to filter processes.</li><li>Easy switching between sorting options.</li><li>Send SIGTERM, SIGKILL, SIGINT to selected process.</li><li>UI menu for changing all config file options.</li><li>Auto scaling graph for network usage.</li><li>Shows message in menu if new version is available</li><li>Shows current read and write speeds for disks</li><li>Multiple data collection methods which can be switched if running on Linux</li></ul><h2 id="how-to-install-bashtop-on-ubuntu-20-04-or-elementary-os-5-1">How to install Bashtop on Ubuntu 20.04 or Elementary OS 5.1</h2><p>There are basically two methods and both are really simple to follow along. Whole <code>bashtop</code> app is a single bash shell script, a single executable file. No need to build or install anything. </p><h3 id="method-1-manual-installation-using-git-any-linux-distro-osx-freebsd">Method 1: Manual installation using Git - Any Linux distro, OSX, FreeBSD</h3><p><em>You will need to have Git installed before you continue. </em></p><pre><code class="language-bash">cd ~
git clone git@github.com:aristocratos/bashtop.git
cd bashtop
make install</code></pre><p>That&apos;s it! now you can close and reopen you terminal or simply reload your <code>.bashrc</code> or <code>.zshrc</code> and you are ready to go! </p><p>In your terminal run <code>bashtop</code> whenever you wish to have a look or kill some process. </p><p><strong>If you ever wish to uninstall bash top that was installed this way, you can easily do that by running this command</strong></p><pre><code class="language-bash">cd ~/bashtop
make uninstall
cd ..
rm -rf bashtop</code></pre><h3 id="method-2-ubuntu-and-elementary-os-install-from-ppa-repo">Method 2: Ubuntu and Elementary OS - install from ppa repo</h3><p>Run the following commands in terminal</p><pre><code>sudo add-apt-repository ppa:bashtop-monitor/bashtop
sudo apt update
sudo apt install bashtop</code></pre><p>Uninstall as any other app installed using <strong>apt-get </strong></p><pre><code class="language-bash"> sudo apt-get --purge remove bashtop
 sudo apt-get autoremove</code></pre><h2 id="cpu-core-temperature-">CPU Core temperature:</h2><p><em>for ubuntu, elementary os, and other debian-based distros</em></p><p>One of the most awesome features <code>bashtop</code> provides is temperature for each individual CPU core/thread. For <code>bashtop</code> to be able to show the temperature, you will need to install one of the libraries that are can obtain and provide that info. Simply run this command in terminal and next time you run <code>bashtop</code> it will show you temperature readings for CPU cores. </p><pre><code>sudo apt-get install lm-sensors </code></pre><blockquote>You can learn more about installation on different linux distros on the <code>bashtop</code> <a href="https://github.com/aristocratos/bashtop#installation">GitHub repo</a> </blockquote><h2 id="options-menu">Options menu</h2><p>Bashtop comes with various settings - from themes to refresh rate at which data on the screen will be refresh at. To access this menu just press <strong>ESC.</strong></p><figure class="kg-card kg-image-card"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-01-25-14.png" class="kg-image" alt="Bye htop, hello bashtop" loading="lazy"></figure><p>Select <strong>OPTIONS </strong>then press <strong>Enter</strong> key</p><h3 id="themes">Themes</h3><p>There are 10 additional themes that come together with the installation. Select <strong>Themes </strong>option and press <strong>Enter</strong> key to tell <code>bashtop</code> to look for new themes in the themes directory.</p><figure class="kg-card kg-image-card"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-01-25-32.png" class="kg-image" alt="Bye htop, hello bashtop" loading="lazy"></figure><p> &#xA0;Change the theme using <strong>left </strong>and <strong>right </strong>arrow keys</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-35-41-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-35-41-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-35-41-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-35-41-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-35-41-1.png 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-35-55-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-35-55-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-35-55-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-35-55-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-35-55-1.png 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-04-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-04-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-04-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-04-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-04-1.png 1920w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-12-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-12-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-12-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-12-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-12-1.png 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-20-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-20-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-20-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-20-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-20-1.png 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-26-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-26-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-26-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-26-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-26-1.png 1920w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-31-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-31-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-31-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-31-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-31-1.png 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-38-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-38-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-38-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-38-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-38-1.png 1920w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-45-1.png" width="1920" height="1080" loading="lazy" alt="Bye htop, hello bashtop" srcset="https://blog.marjanovic.me/content/images/size/w600/2020/06/Screenshot-from-2020-06-05-08-36-45-1.png 600w, https://blog.marjanovic.me/content/images/size/w1000/2020/06/Screenshot-from-2020-06-05-08-36-45-1.png 1000w, https://blog.marjanovic.me/content/images/size/w1600/2020/06/Screenshot-from-2020-06-05-08-36-45-1.png 1600w, https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-08-36-45-1.png 1920w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="keyboard-shortcuts">Keyboard shortcuts </h2><p>To learn about different keyboard shortcuts you can use, go to the <strong>OPTIONS</strong> menu, and then select <strong>HELP</strong></p><figure class="kg-card kg-image-card"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-05-00-50-10.png" class="kg-image" alt="Bye htop, hello bashtop" loading="lazy"></figure><h3 id="conclusion">Conclusion</h3><p>Bashtop is certainly a refresh and interesting how terminal apps can look amazing. &#xA0;I hope this article has inspired you to give <code>bashtop</code> a chance and you enjoy using it.</p><hr><h3 id="references-and-useful-resources">References and useful resources</h3><p><a href="https://www.youtube.com/redirect?v=A6fdSHtPHAM&amp;redir_token=ccIj8ZXDmkk1Qd8F6JMcDiwpJch8MTU5MTQyODYyNkAxNTkxMzQyMjI2&amp;event=video_description&amp;q=https%3A%2F%2Fgithub.com%2Faristocratos%2Fbashtop" rel="nofollow">https://github.com/aristocratos/bashtop</a><br><a href="https://computingforgeeks.com/bashtop-resource-monitor-for-linux-macos-freebsd/">https://computingforgeeks.com/bashtop-resource-monitor-for-linux-macos-freebsd/</a><br><a href="https://www.youtube.com/watch?v=nyx9AqaqUgA">https://www.youtube.com/watch?v=nyx9AqaqUgA</a><br><a href="https://www.youtube.com/watch?v=A6fdSHtPHAM">https://www.youtube.com/watch?v=A6fdSHtPHAM</a></p>]]></content:encoded></item><item><title><![CDATA[How to set up trackpad gestures on ElementaryOS and Ubuntu]]></title><description><![CDATA[<p>If you by any chance had an opportunity to use a trackpad on MacBook or even better a Magic Trackpad I highly doubt you weren&apos;t amazed. I know I was. It&apos;s definitly one of few things I missed the most when switched from MacBook Pro to</p>]]></description><link>https://blog.marjanovic.me/how-to-set-up-macbook-like-gestures-on-ubuntu-and-elementaryos/</link><guid isPermaLink="false">6166e347aa72900001903e84</guid><category><![CDATA[ubuntu]]></category><category><![CDATA[elementaryos]]></category><category><![CDATA[usability]]></category><category><![CDATA[gestures]]></category><category><![CDATA[trackpad]]></category><category><![CDATA[touchpad]]></category><dc:creator><![CDATA[Srdjan Marjanovic ]]></dc:creator><pubDate>Tue, 02 Jun 2020 00:01:02 GMT</pubDate><media:content url="https://blog.marjanovic.me/content/images/2020/06/photo-1490470543201-3a33602c9f85.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.marjanovic.me/content/images/2020/06/photo-1490470543201-3a33602c9f85.jpg" alt="How to set up trackpad gestures on ElementaryOS and Ubuntu"><p>If you by any chance had an opportunity to use a trackpad on MacBook or even better a Magic Trackpad I highly doubt you weren&apos;t amazed. I know I was. It&apos;s definitly one of few things I missed the most when switched from MacBook Pro to ThinkPad T490. Eventhough ThinkPad&apos;s keyboard is by far superior to Mac&apos;s, the trackpad is... meh. Nontheless, it is a multitouch device and that means I can use it with swipe and pinch gestures to supercharge my workflow. </p><p>Sadly, I don&apos;t know about any Linux distro that comes with a usable gesture support. No worries, that&apos;s why this tutorial exists. </p><p><code>libinput</code> is a library that adds various gestures support to the OS. </p><p>In order to be allowed to use gestures, your user must be added to the <code>input</code> group</p><p>In terminal, type the following command and enter your password</p><pre><code class="language-bash">sudo gpasswd -a $USER input
</code></pre><p><strong>After that, you will have to logout, and log back in order for the changes to take effect. </strong></p><p>Install packages needed to install and use app for creating and mapping gestures.</p><pre><code class="language-bash">sudo apt-get install wmctrl python3 python3-setuptools xdotool python3-gi libinput-tools python-gobject</code></pre><p>After that, clone the <code>libinput-gestures</code> to your Downloads directory:</p><pre><code class="language-bash">cd ~/Downloads
git clone https://github.com/bulletmark/libinput-gestures.git
cd libinput-gestures
sudo make install</code></pre><p>To be sure that this utility is started whenever your computer is turned on, we need to run the following commands:</p><pre><code class="language-bash">libinput-gestures-setup autostart
libinput-gestures-setup start
</code></pre><p>At this point, you can create a config file to map gestures to actions which I&apos;ll cover in another tutorial. For the sake of simplicity, we&apos;ll stick with a GUI app for this one.</p><p>To install Gestures GUI app, run following commands:</p><pre><code class="language-bash">cd ~/Downloads
git clone https://gitlab.com/cunidev/gestures.git
cd gestures
sudo python3 setup.py  install</code></pre><h3 id="mapping-gestures-to-actions">Mapping gestures to actions</h3><p>Run <strong>Gestures </strong>app from the Applications menu. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.marjanovic.me/content/images/2020/06/Screenshot-from-2020-06-02-01-02-25.png" class="kg-image" alt="How to set up trackpad gestures on ElementaryOS and Ubuntu" loading="lazy"><figcaption><a href="https://gitlab.com/cunidev/gestures">https://gitlab.com/cunidev/gestures</a></figcaption></figure><p>Start by adding new gesture. Simply click <strong>+</strong> icon in the upper-left corner. </p><figure class="kg-card kg-image-card"><img src="https://blog.marjanovic.me/content/images/2020/06/image-1.png" class="kg-image" alt="How to set up trackpad gestures on ElementaryOS and Ubuntu" loading="lazy"></figure><p>In the pop-up choose which type of gesture you wish to add - <strong>Swipe</strong> or <strong>Pinch</strong>. Next, choose a direction: <strong>Up</strong>, <strong>Down</strong>, <strong>Left</strong>, <strong>Right</strong> for the <strong>Swipe</strong> type of gesture and <strong>In</strong>, <strong>Out</strong>, <strong>Clockwise</strong>, <strong>Anticlockwise</strong> for the <strong>Pinch</strong>. After that, select how &#xA0;many fingers the gesture is consisted of. In the <strong>Command field</strong> you should enter a command which will be executed when geture occures. For this, we will use <strong>xdotool </strong>which we installed at the beginning. It is a simple utility that programatically &quot;fakes&quot; keyboard and mouse events. Will use it to trick our OS to think we pressed a keyboard shortcut. </p><p>The way I use setup my gestures is:</p><p><strong>4-finger swipe left</strong> perform <code>xdotool key super+Right</code> (Switch to workspace right)<br><strong>4-finger swipe right</strong> perform <code>xdotool key super+Left</code> (Switch to workspace left)<br><strong>4-finger swipe up</strong> perform <code>xdotool key super+Up</code> (<br>Toggle maximized)<br>&#x200C;<strong>4-finger swipe down</strong> perform <code>xdotool key super+Down</code> (&#x200C;<br>&#x200C;Multitasking view, same as <strong>super+S</strong>)<br><strong>3-finger swipe left</strong> perform <code>xdotool key alt+Left</code> (<br>Browser back)<br><strong>3-finger swipe right</strong> perform <code>xdotool key alt+Right</code> (<br>Browser forward)</p><p>Add getures one by one and click confirm.<br><em>For the swipe action, <strong>Two</strong> fingers option might be disabled because it&apos;s already provided by the touchpad itself for scrolling. &#xA0;</em></p><p>As a last step, we can clean up &#xA0;by safely removing cloned repositories</p><pre><code class="language-bash">rm -rf ~/Downloads/libinput-gestures
rm -rf ~/Downloads/gestures</code></pre><p>I hope this helps you in your everyday work, I sure know it helped me :)</p><hr><p>Here are some links and references related to the libraries mentioned in this article</p><!--kg-card-begin: markdown--><ul>
<li><a href="https://github.com/jordansissel/xdotool">https://github.com/jordansissel/xdotool</a></li>
<li><a href="https://www.semicomplete.com/projects/xdotool/">https://www.semicomplete.com/projects/xdotool/</a></li>
<li><a href="https://github.com/bulletmark/libinput-gestures">https://github.com/bulletmark/libinput-gestures</a></li>
<li><a href="https://gitlab.com/cunidev/gestures/-/tree/devel">https://gitlab.com/cunidev/gestures/-/tree/devel</a></li>
<li><a href="https://www.youtube.com/watch?v=ArBCfhVsTZw">https://www.youtube.com/watch?v=ArBCfhVsTZw</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Hello world]]></title><description><![CDATA[I've written so many these introductory posts in all the previous failed attempts to start a blog that I have stopped counting long time ago. On the other hand, I never stopped wishing to have a personal space of my own, so here's another shot. I would really like this one to succeed. ]]></description><link>https://blog.marjanovic.me/hello/</link><guid isPermaLink="false">6166e347aa72900001903e82</guid><category><![CDATA[Hello]]></category><category><![CDATA[About]]></category><dc:creator><![CDATA[Srdjan Marjanovic ]]></dc:creator><pubDate>Wed, 06 May 2020 00:16:58 GMT</pubDate><media:content url="https://blog.marjanovic.me/content/images/2020/05/20191003_135227.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="who-am-i">Who am I?</h3><img src="https://blog.marjanovic.me/content/images/2020/05/20191003_135227.jpg" alt="Hello world"><p>My name is Sr&#x111;an Marjanovi&#x107;. I live in Novi Sad, Serbia. My list of things that I&apos;m passionate about is ever evolving but some of the stuff that are always present on the list are of course programming, hacking and tinkering with computers and electronics, but also cooking, coffee, skiing, rollerblading, ice skating and photography. </p><p>I have almost a decade of professional experience as a web developer. Currently, my day job is being a full stack developer (with a sprinkle of Ops) @ <a href="www.activecollab.com">Active Collab</a>. I&apos;m a part of one of the multidisciplinary scrum teams. My team is doing the magic behind the scene. We are in charge of servers, services and payments run smoothly. Also, we take care of our back office system that helps our support and success teams help our customers and our business development and design teams to better understand the needs of our clients. Every day we juggle with multiple services written using several technology stacks that are running both on AWS and bare metal servers. Some are real-time, all are highly-available. </p><h3 id="why-am-i-doing-this">Why am I doing this?</h3><p>One of the main motives is that I always felt that I have many things to share with the world (outside of my soical media postings), but not just that. One way communication sucks. I would really want to spark discussions with all of you who come across this corner of the Internet. </p><p>On the other hand, I needed a place to articulate my thoughts and ideas and to have a reference of how I overcame some issues. </p><p>They say that if you really want to be sure you understand something, you need to be able to explain it to someone else, and that is my main motive - to learn by teaching. <br><br>Also, you probably noticed that I&apos;m not a native english speaker and I hope that my english will improve while writing these posts.</p><h3 id="what-can-you-expect-to-find-here">What can you expect to find here?</h3><p>As I&apos;m passionate about some totally different stuff, it might get messy, but I will try to keep things down to:</p><ol><li><strong>Programming</strong> - PHP, MySQL, Golang, Python, JS, CSS, shell, refactoring, testing ...</li><li><strong>Electronics</strong> - Arduino, Raspberry Pi, sensors, motors ...</li><li><strong>DevOps</strong> - Jenkings, GitLab, Grafana, Prometheus, CI/CD, linux, servers, monitoring, automation ...</li><li><strong>Productivity</strong> - routines, habbits, lifehacks, tools, methodologies ...</li><li><strong>Personal</strong> - thoughts about books, videos, talks, shows ...</li></ol><h3 id="how-often-will-i-publish-new-posts">How often will I publish new posts?</h3><p>It really depends. I have almost no free time at all as I&apos;m working full time and I have several small kids to raise. I will probobly write in bursts in moments of inspiration and free time. </p><p>Until the next reading, have a great time</p>]]></content:encoded></item></channel></rss>