<?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"><channel><title><![CDATA[My Random Adventures]]></title><description><![CDATA[I'm a dedicated software engineer with a passion for bringing hardware and software together to create robust solutions. I thrive on optimizing performance, and ensuring the reliability of devices.]]></description><link>https://blog.asankasovis.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1752905208799/9a7bf29d-6cc8-4dec-aa71-81396ae122da.png</url><title>My Random Adventures</title><link>https://blog.asankasovis.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 10:46:07 GMT</lastBuildDate><atom:link href="https://blog.asankasovis.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to do Better Logging]]></title><description><![CDATA[When you're working on Embedded firmware or low level development, it's important to have a proper logging system in place. Logging helps with debugging, tracking values and monitoring the system for ]]></description><link>https://blog.asankasovis.com/how-to-do-better-logging</link><guid isPermaLink="true">https://blog.asankasovis.com/how-to-do-better-logging</guid><category><![CDATA[C]]></category><category><![CDATA[C++]]></category><category><![CDATA[printf]]></category><category><![CDATA[logging]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Fri, 27 Feb 2026 04:24:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/61a2243af0cb2e37690c63e1/d3d49fab-6d1b-4fab-96d4-89d4496e0021.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you're working on Embedded firmware or low level development, it's important to have a proper logging system in place. Logging helps with debugging, tracking values and monitoring the system for the health. But there are situations where we need to disable all logs; let's say for a release or for performance benchmarking.</p>
<p>What easily comes to mind is to comment out all the <code>printf</code> statements and recompiling. But, imagine a codebase with hundreds of thousands of logs. It will get quite tedious to get rid of all the logs, and it's also easy to miss some.</p>
<p>Another option would be to wrap all <code>printf</code> statements with an <code>ifdef</code>. For example:</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

#define DEBUG

int main() {
#ifdef DEBUG
    printf("Hello...");
#endif
}
</code></pre>
<p>If <code>DEBUG</code> is defined, <code>printf</code> will be there and when it's not, the <code>printf</code> will not be there in the final compiled binary.</p>
<p>But this is also quite inefficient. Imagine having to write three lines instead of one for a simple print statement, not to mention the complication of a trivial task like printing a message. The reason that I'm telling this is that there's a better option.</p>
<p>What if instead of directly using <code>printf</code>, we create a macro to transform it into some other form, but then we use another macro to select which form that we're using? This is exactly where the optimum way to do logging lies. Here's a sample code:</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

#define DEBUG 1

#if DEBUG
    #define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
#else
    #define LOG(fmt, ...) 
#endif

int main() {
    int connection_count = 5;
    
    LOG("Server started successfully.");
    LOG("Current connections: %d", connection_count);

    return 0;
}
</code></pre>
<p>Notice how there's an <code>if</code> macro which chooses between two forms for a function we define as <code>LOG(fmt, ...)</code>. In case <code>DEBUG</code> is <code>1</code>, it automatically turns into <code>printf(fmt "\n", ##__VA_ARGS__)</code>, the <code>printf</code> we know and love. But if it's <code>0</code>, it turns into nothing. This creates a simple, efficient and clean way to enable and disable logs. You just have to write <code>LOG(...)</code> like you're used to and then define <code>DEBUG</code> as <code>1</code> or <code>0</code> to enable or disable the logging.</p>
<p>The keen eyed among you might worry if this might end up with unwanted instructions in your code. The thing is, modern compilers will happily compile this code without any overhead. Still don't believe me? Checkout this sample code in <a href="https://godbolt.org/">Compiler Explorer</a>: <a href="https://godbolt.org/z/3c4qfvM3E">https://godbolt.org/z/3c4qfvM3E</a>.</p>
<p>The assembly for the case of <code>DEBUG</code> is <code>1</code> turns out to be:</p>
<pre><code class="language-c">.LC0:
        .string "Server started successfully."
.LC1:
        .string "Current connections: %d\n"
main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:.LC0
        call    puts
        mov     esi, 5
        mov     edi, OFFSET FLAT:.LC1
        xor     eax, eax
        call    printf
        xor     eax, eax
        add     rsp, 8
        ret
</code></pre>
<p>Try turning <code>DEBUG</code> to <code>0</code> and see the compilation. It will turn out to be:</p>
<pre><code class="language-c">main:
        xor     eax, eax
        ret
</code></pre>
<p>As you can see, the whole logging statements disappeared without any residual code.</p>
<p>Thus, we can see that this eliminates all the issues we had with the previous two methods. In fact most modern code uses this technique for logging. So make sure to use this in your next project.</p>
]]></content:encoded></item><item><title><![CDATA[The C Runtime?]]></title><description><![CDATA[I always thought that when we compile a C code, it ‘just works’. No other fancy code runs to make our code function, like in the case for Java and Python. But turns out, it’s not exactly true. There are some work that happens behind the scenes when w...]]></description><link>https://blog.asankasovis.com/the-c-runtime</link><guid isPermaLink="true">https://blog.asankasovis.com/the-c-runtime</guid><category><![CDATA[C]]></category><category><![CDATA[C++]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Fri, 13 Feb 2026 14:02:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770991234992/ca38fd27-95af-4b59-832d-3f18585434ce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I always thought that when we compile a C code, it <em>‘just works’</em>. No other fancy code runs to make our code function, like in the case for Java and Python. But turns out, it’s not <em>exactly</em> true. There are some work that happens behind the scenes when we run a binary written in C.</p>
<p>This code is called the <strong>C Runtime (CRT)</strong>, but don’t confuse this with the Java Runtime Environment (JRE) or the Python Runtime Environment (PRE). Unlike Java and Python code, C code directly runs on the bare-metal, but there does exist some work that needs to be done before, while and after our code runs. This is handled by the C Runtime. Let’s dive a bit deeper…</p>
<p>The CRT consists of four main components:</p>
<ul>
<li><p><strong>Startup Sequence:</strong> Before our <code>main()</code> function even runs, the CRT performs initialization. It sets up the stack, initializes global variables, and gathers command-line arguments.</p>
</li>
<li><p><strong>Memory Management:</strong> It provides the logic for functions like <code>malloc()</code> and <code>free()</code>, managing the "Heap" memory, so our program can request space dynamically.</p>
</li>
<li><p><strong>Standard Library (<em>libc</em>):</strong> This is the bulk of the CRT. It includes the math functions, string manipulation tools, and input/output handlers (like <code>printf()</code> and <code>scanf()</code>).</p>
</li>
<li><p><strong>The Stack and Heap:</strong> The CRT manages the memory layout. The Stack handles local variables and function calls, while the Heap handles dynamic data.</p>
</li>
</ul>
<p>Let’s dive a little bit deeper into these four tasks of the CRT.</p>
<h1 id="heading-the-startup-sequence-the-c-bootstrap">The Startup Sequence (The "C Bootstrap")</h1>
<p>When we click "Run," the Operating System doesn't jump straight to our <code>int main()</code>. It jumps to an entry point provided by the CRT (often called <code>_start</code> or <code>mainCRTStartup</code>).</p>
<ul>
<li><p><strong>Setting the Environment:</strong> The CRT retrieves the Environment Variables (like <em>PATH</em>) and the Command Line Arguments from the OS. It parses them into the <code>argc</code> and <code>argv</code> parameters we see in <code>main()</code>.</p>
</li>
<li><p><strong>Initialization of Statics:</strong> It clears the BSS segment (setting un-initialized global variables to zero) and copies initial values into the Data segment for variables like <code>int x = 10;</code>.</p>
</li>
<li><p><strong>Constructors:</strong> In C++ (or C with specific compiler extensions), the CRT calls "global constructors" before main starts.</p>
</li>
<li><p><strong>The Handshake:</strong> Finally, it calls <code>main()</code>. When <code>main()</code> finishes, the CRT takes the return value (e.g., 0) and passes it back to the OS via an <code>exit()</code> system call.</p>
</li>
</ul>
<h1 id="heading-memory-management-malloc-and-free">Memory Management (<code>malloc</code> and <code>free</code>)</h1>
<p>The Operating System is strict; it only gives memory to programs in large "pages" (usually 4KB). If we only need 20 bytes, asking the OS directly is incredibly slow and wasteful.</p>
<ul>
<li><p><strong>The Middleman:</strong> The CRT maintains a "pool" of memory. When we call <code>malloc(20)</code>, the CRT looks at its pool, carves out 20 bytes, marks them as "in use," and gives you the pointer.</p>
</li>
<li><p><strong>Bookkeeping:</strong> The CRT keeps a hidden header just before our pointer that stores the size of the block. This is how <code>free()</code> knows exactly how much memory to release without us telling it the size.</p>
</li>
<li><p><strong>Heap Expansion:</strong> If the CRT runs out of memory in its pool, it issues a system call (like <code>sbrk</code> on Linux or <code>VirtualAlloc</code> on Windows) to ask the OS for another big chunk of RAM.</p>
</li>
</ul>
<h1 id="heading-the-stack-vs-the-heap">The Stack vs. The Heap</h1>
<p>These are the two primary ways a program uses RAM, and the CRT (along with the CPU) manages the boundary between them.</p>
<ul>
<li><p><strong>The Stack:</strong> Every time we call a function, the CRT pushes a "Frame" onto the stack. This frame holds our local variables and the "return address" (where to go when the function ends).</p>
</li>
<li><p><strong>The Heap:</strong> The "pile" of memory used for data that needs to live a long time or is too big for the stack (like a high-resolution image).</p>
</li>
</ul>
<h1 id="heading-the-standard-library-libc">The Standard Library (<code>libc</code>)</h1>
<p>This is the "toolbox" of C. It is a collection of pre-compiled code that performs common tasks that would be hard to write from scratch.</p>
<ul>
<li><p><strong>System Call Wrappers:</strong> Functions like <code>printf()</code> or <code>fopen()</code> are wrappers. They take our high-level request, format it, and then perform a System Call to ask the OS kernel to actually write pixels to a screen or bits to a disk.</p>
</li>
<li><p><strong>Portability Layer:</strong> <code>libc</code> is the reason our code can run on both Windows and Linux. On Windows, <code>printf()</code> might call <code>WriteFile</code>, while on Linux, it calls <code>write</code>. We don't have to care; the CRT handles the translation.</p>
</li>
<li><p><strong>Utility Functions:</strong> These are pure logic. Things like <code>sqrt()</code>, <code>strlen()</code>, or <code>sort()</code>. They don't talk to the OS; they just provide optimized algorithms so we don't have to reinvent the wheel.</p>
</li>
</ul>
<h1 id="heading-the-code">The Code</h1>
<p>Curious as to how these are managed? Checkout the <a target="_blank" href="https://github.com/bminor/glibc/tree/master">glibc repository</a> to see these components in action. The <code>_start</code> code is under <code>sysdeps/x86_64/start.S</code>. This is in Assembly to facilitate the required low-level work. The memory allocation logic is under <code>malloc/malloc.c</code>. This is quite a complicated bit of code.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>So what did we learn? Even C is not about compile and run. There’s a lot more happening under the hood than what we’re doing ourselves. It’s quite interesting how far these tools have come. So next time you write a new <code>main()</code>, think of all the work happening under the hood that keeps your code running correctly.</p>
]]></content:encoded></item><item><title><![CDATA[Are Switch Statements Better than If-else?]]></title><description><![CDATA[Ever heard tech bros say, ‘switch statements are more efficient than if-else statements’? I certainly have. But have you thought of whether this is actually true? Well, is it actually true? The answer is that ‘it’s complicated!’ Let’s discuss.
While ...]]></description><link>https://blog.asankasovis.com/are-switch-statements-better-than-if-else</link><guid isPermaLink="true">https://blog.asankasovis.com/are-switch-statements-better-than-if-else</guid><category><![CDATA[C]]></category><category><![CDATA[C++]]></category><category><![CDATA[compiler]]></category><category><![CDATA[Computer Science]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Fri, 23 Jan 2026 09:01:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769158778749/52f1e08a-b568-4c47-a299-414f2dac663c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever heard tech bros say, ‘switch statements are more efficient than if-else statements’? I certainly have. But have you thought of whether this is actually true? Well, is it actually true? The answer is that ‘it’s complicated!’ Let’s discuss.</p>
<p>While this statement has a good technical value to it, this is not always the case. Switch statements are highly optimized and can outperform regular if-else statements under specific conditions. Let’s start with the basics: what is a switch statement?</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">use_if_else</span><span class="hljs-params">(<span class="hljs-keyword">int</span> value)</span> </span>{
    <span class="hljs-keyword">if</span> (value == <span class="hljs-number">1</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">102</span>;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (value == <span class="hljs-number">2</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">15</span>;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (value == <span class="hljs-number">3</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">888</span>;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (value == <span class="hljs-number">4</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">42</span>;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (value == <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">7</span>;
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }
}
</code></pre>
<p>You might be familiar with the above code. This is a simple example of an if-else statement. But a switch statement for the same task looks like this:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">use_switch</span><span class="hljs-params">(<span class="hljs-keyword">int</span> value)</span> </span>{
    <span class="hljs-keyword">switch</span> (value) {
        <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">102</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">15</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">888</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">42</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-number">5</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">7</span>;
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }
}
</code></pre>
<p>But how can this be more efficient than an if-else statement? The answer is actually in the underlying assembly interpretation. Let’s compare the compiled assembly representation of the two functions.</p>
<pre><code class="lang-c">use_if_else:
        cmp     edi, <span class="hljs-number">1</span>
        je      .L3
        cmp     edi, <span class="hljs-number">2</span>
        je      .L4
        cmp     edi, <span class="hljs-number">3</span>
        je      .L5
        cmp     edi, <span class="hljs-number">4</span>
        je      .L6
        cmp     edi, <span class="hljs-number">5</span>
        mov     eax, <span class="hljs-number">0</span>
        mov     edx, <span class="hljs-number">7</span>
        cmove   eax, edx
        ret
.L3:
        mov     eax, <span class="hljs-number">102</span>
        ret
.L4:
        mov     eax, <span class="hljs-number">15</span>
        ret
.L5:
        mov     eax, <span class="hljs-number">888</span>
        ret
.L6:
        mov     eax, <span class="hljs-number">42</span>
        ret
</code></pre>
<p>This is how the compiled Assembly looks like for the if-else code. Below is for the switch statement. You can see it in compiler explorer: <a target="_blank" href="https://godbolt.org/z/K9MzEjK77">https://godbolt.org/z/K9MzEjK77</a></p>
<pre><code class="lang-c">use_switch:
        cmp     edi, <span class="hljs-number">5</span>
        ja      .L2
        mov     edi, edi
        jmp     [QWORD PTR .L4[<span class="hljs-number">0</span>+rdi*<span class="hljs-number">8</span>]]
.L4:
        .quad   .L2
        .quad   .L8
        .quad   .L9
        .quad   .L6
        .quad   .L5
        .quad   .L3
.L8:
        mov     eax, <span class="hljs-number">102</span>
        ret
.L6:
        mov     eax, <span class="hljs-number">888</span>
        ret
.L5:
        mov     eax, <span class="hljs-number">42</span>
        ret
.L3:
        mov     eax, <span class="hljs-number">7</span>
        ret
.L2:
        mov     eax, <span class="hljs-number">0</span>
        ret
.L9:
        mov     eax, <span class="hljs-number">15</span>
        ret
</code></pre>
<p>As we can see, the two codes produce completely different Assembly code. But still, both of them seem to be close to the same length. How can one be more optimized than the other? It’s all about how the code is executed. Imagine the scenario of receiving <code>value = 5</code> in the if-else statement. It has to go through all the <code>cmp</code> and <code>jmp</code> instructions before we reach the <code>value = 5</code> situation. But in case of the switch statement, it multiplies the value of <code>value</code> with 8, (because each address in the table is 8 bytes long) and jump that amount forward. Which lands us immediately at the <code>mov</code> and <code>ret</code> commands for the value of <code>7</code>. This is called a <strong>‘Jump Table’</strong>.</p>
<p>So, while the if-else statement was looking one after the other for the condition of <code>value = 5</code>, the switch statement <em>mathematically</em> moved execution to the <strong>5th</strong> instruction. See below for a simplified breakdown.</p>
<pre><code class="lang-plaintext">if-else:
is 1 = 5? --&gt; no, then is 2 = 5? --&gt; no, then is 3 = 5? --&gt; no, then is 4 = 5 no, then is 5 = 5, yes, then return 7
</code></pre>
<pre><code class="lang-plaintext">switch:
move 5 steps below --&gt; return the value there
</code></pre>
<p>Now imagine hundreds of possible <code>value</code>s. The execution time saved can be staggering. For those of you curious, the if-else statement gave us <em>O(n)</em> and the switch statement gave us <em>O(1)</em>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769157779874/b2b929d1-74be-47fe-8347-ff44d136a3e9.png" alt class="image--center mx-auto" /></p>
<p>However, this is not always the case. If the conditions don’t follow a mathematical pattern, this falls apart and we don’t see much difference.</p>
<p>However, if you paid close attention, you see that I used a compiler flag called <code>-fno-jump-tables</code> in the if-else statement. This is because modern compilers are smart to identify the existence of a jump table, even in an if-else statement.</p>
<p>But, does this mean that it’s not useful to use a switch statement instead of the if-else? Well, not exactly. The switch statement is a lot more elegant in certain code patterns. Also, sometimes the compiler might not be able to identify the pattern and be able to optimize an if-else statement unless you use a switch statement.</p>
<p>In conclusion, switch statements are awesome! But still, with modern smart compilers, it is not always the case that if-else statements are bad. So next time you use an if-else statement for checking an integer, maybe consider using a switch statement.</p>
]]></content:encoded></item><item><title><![CDATA[Fixing the Issue of Failing to Flash Devices Using Arduino on Ubuntu]]></title><description><![CDATA[I recently came across an issue where Arduino, installed under Ubuntu, refused to upload to my ESP32 device stating that ‘/dev/ttyUSB0 is not available or accessible’. This might sound absurd, and after digging into this issue a bit, I think I found ...]]></description><link>https://blog.asankasovis.com/fixing-the-issue-of-failing-to-flash-devices-using-arduino-on-ubuntu</link><guid isPermaLink="true">https://blog.asankasovis.com/fixing-the-issue-of-failing-to-flash-devices-using-arduino-on-ubuntu</guid><category><![CDATA[Ubuntu]]></category><category><![CDATA[arduino]]></category><category><![CDATA[ESP32]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Mon, 01 Sep 2025 16:09:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756742829794/93f84367-57f1-44a0-ac12-ca758d4018d2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently came across an issue where Arduino, installed under Ubuntu, refused to upload to my ESP32 device stating that ‘<em>/dev/ttyUSB0 is not available or accessible’</em>. This might sound absurd, and after digging into this issue a bit, I think I found the issue. This is a security feature implemented by modern Ubuntu. But, the usual suggestion of adding the current user to the <code>dialout</code> user group didn’t work.</p>
<pre><code class="lang-bash">sudo usermod -a -G dialout <span class="hljs-variable">$USER</span>
</code></pre>
<p>This might be a new security feature but, I will give a few pointers on how to actually setup Arduino on your Ubuntu machine.</p>
<h1 id="heading-installation">Installation</h1>
<p>The recommended, and the method I also use, is to install the Arduino IDE through the Flatpak repo. You can install the Classic IDE or the modern IDE. If you do not have Flatpak setup, you can follow the simple <a target="_blank" href="https://flatpak.org/setup/Ubuntu">guide</a> given by the Flatpak developers. Then, you can open the Gnome Software Centre, search for ‘<em>Arduino</em>’, and install the IDE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756742026783/24bda070-b2fc-4738-877f-076cc92197c8.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-uninstalling-brltty">Uninstalling <code>brltty</code></h1>
<p><code>brltty</code> is a preinstalled program on Ubuntu that’s known to cause problems with serial devices. So uninstall it using the following command. Unless you heavily rely on accessibility inputs, this program should not be important to you.</p>
<pre><code class="lang-bash">sudo apt remove brltty
</code></pre>
<h1 id="heading-changing-user-access-to-serial-port">Changing User Access to Serial Port</h1>
<p>This actual fix is to give permission to the current user to access <code>/dev/ttyUSB0</code> or whatever device that you have connected to Arduino. You can see the serial port that Arduino is trying to connect to. Use the following command to give your user the access to this device. Note that every time you disconnect and reconnect the device, you have to run this command.</p>
<pre><code class="lang-bash">sudo chmod a+rw /dev/ttyUSB0
</code></pre>
<p>Here, <code>/dev/ttyUSB0</code> is the device that I want to connect to, yours may vary, and you have to add this here instead of <code>/dev/ttyUSB0</code>. <code>sudo</code> provides admin privileges to the current command, <code>chmod</code> asks the device to edit access, <code>a</code> indicates the current user, <code>+rw</code> indicates read + write access and finally, <code>/dev/ttyUSB0</code> is the device.</p>
<p>Not sure which device to connect to? An easy way is to use the following command.</p>
<pre><code class="lang-bash">ls /dev/tty*
</code></pre>
<p>This lists all the serial devices currently connected to your computer. In most cases, the device might be called <code>ttyUSB0</code> or any other variant of <code>ttyUSB…</code>. First run this command without the device attached, then run again WITH the device attached and see which device appeared. This is the serial device. You can use that to upload your code.</p>
<p>Hope this helps, I will continue to update this post with any further information I find on this matter, including any permanent fixes as well.</p>
]]></content:encoded></item><item><title><![CDATA[Kernel Driver Not Installed Issue with VirtualBox]]></title><description><![CDATA[There’s a nasty issue in VirtualBox where you won’t be able to run virtual machines on Linux distros. The error shows something similar to:
Kernel driver not installed (rc=-1908)

The VirtualBox Linux kernel driver is either not loaded or not set up ...]]></description><link>https://blog.asankasovis.com/kernel-driver-not-installed-issue-with-virtualbox</link><guid isPermaLink="true">https://blog.asankasovis.com/kernel-driver-not-installed-issue-with-virtualbox</guid><category><![CDATA[VirtualBox ]]></category><category><![CDATA[Ubuntu]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Fri, 22 Aug 2025 08:12:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1755850286536/ca7ebed2-bfd8-4e53-8b06-61b518f59528.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There’s a nasty issue in VirtualBox where you won’t be able to run virtual machines on Linux distros. The error shows something similar to:</p>
<pre><code class="lang-plaintext">Kernel driver not installed (rc=-1908)

The VirtualBox Linux kernel driver is either not loaded or not set up correctly. Please reinstall virtualbox-dkms package and load the kernel module by executing

'modprobe vboxdrv'

as root.

If your system has EFI Secure Boot enabled you may also need to sign the kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load them. Please see your Linux system's documentation for more information.

where: suplibosinit what: 3
VERR_VM_DRIVER_NOT_INSTALLED (-1908) - The support driver is not installed. On linux, open returned ENOENT.
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1755833442985/a6b13e21-5705-46fb-8895-5b689b04d339.png" alt class="image--center mx-auto" /></p>
<p>The error suggests running <code>modprobe vboxdrv</code> as root, but this shows an error similar to the following:</p>
<pre><code class="lang-bash">modprobe: ERROR: could not insert <span class="hljs-string">'vboxdrv'</span>: Key was rejected by service
</code></pre>
<h1 id="heading-the-issue">The Issue</h1>
<p>The issue lies in Secure Boot. Your computer might have secure boot enabled, as is in most modern computers. Secure Boot is a security feature designed to prevent malicious software from loading during the boot process. It works by ensuring that every piece of code, including the operating system and its drivers, is signed with a trusted digital signature. Secure boot requires that any kernel module loaded be signed with a key that your system's Secure Boot trusts.</p>
<h1 id="heading-the-easiest-solution-not-recommended">The Easiest Solution (Not Recommended)</h1>
<p>The easiest solution is to go to your computer’s BIOS and disable secure boot. But this is both a security risk and a potential issue. It is important to not mess around with security, so do this option if you want to take the risk.</p>
<h1 id="heading-the-actual-fix">The Actual Fix</h1>
<h2 id="heading-setup">Setup</h2>
<p>Before we begin, it is important that we install the latest VirtualBox program. You can find it in the <a target="_blank" href="https://www.virtualbox.org/wiki/Downloads">Downloads</a> page of the VirtualBox website. Download the appropriate package for your distribution and install it using:</p>
<pre><code class="lang-plaintext">sudo apt install ./virtualbox-7.2_7.2.0-170228~Ubuntu~oracular_amd64.deb
</code></pre>
<p>The package name might be different in your situation, so make sure you modify the command accordingly.</p>
<h2 id="heading-applying-the-fix">Applying the Fix</h2>
<p>The first step is to install the <code>mokutil</code> package. <code>mokutil</code> is a command-line utility for Linux that provides a user-friendly way to manage the <strong>Machine Owner Key (MOK)</strong> list, which is a crucial component for systems with UEFI Secure Boot enabled. It allows you to import, delete, and list cryptographic keys that are used to sign bootloaders and kernel modules, like the VirtualBox driver. This tool acts as a bridge between the Linux user space and the firmware's Secure Boot key databases, allowing you to add new trusted keys without having to disable Secure Boot entirely.</p>
<p>To install <code>mokutil</code>, use the following command. This is given to align with the <code>apt</code> package manager which is common in most Debian based distributions such as Ubuntu and Cinnamon. Make sure to look into how you can install the same thing, if you do not have a Debian based system.</p>
<pre><code class="lang-bash">sudo apt-get update
sudo apt-get install mokutil
</code></pre>
<p>Follow the usual way that you install a package on Linux and you should be good.</p>
<p>Next, we will create an RSA key. To do this, first let’s switch to the root user using the following command.</p>
<pre><code class="lang-bash">sudo su
</code></pre>
<p>Once you have root user access, we will create a new folder to handle key signing related work and move into it.</p>
<pre><code class="lang-bash">mkdir /root/signed-modules
<span class="hljs-built_in">cd</span> /root/signed-modules
</code></pre>
<p>Now we’re ready to create the RSA key. Use the following command to create the RSA key.</p>
<pre><code class="lang-bash">openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj <span class="hljs-string">"/CN=VirtualBox/"</span>
chmod 600 MOK.priv
</code></pre>
<p>Next, we will install this key to the kernel using the following command. This will ask for a password. Make sure to remember the password you provided, as this comes in handy later.</p>
<pre><code class="lang-bash">mokutil --import MOK.der
</code></pre>
<p>Now reboot your computer and on reboot, you will see a blue screen which ask for the certificate. Move through this menu as <code>Enroll MOK</code> &gt; <code>Continue</code> &gt; <code>&lt;previous password&gt;</code>. The computer will now turn on as expected.</p>
<p>Once rebooted, we will log back in as the root to do the signing.</p>
<pre><code class="lang-bash">sudo su
</code></pre>
<p>Enter the following command to find where the file signing command is.</p>
<pre><code class="lang-bash">find /usr/src -name sign-file
</code></pre>
<p>Now we will move into our working folder and create a new script to automate our signing.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /root/signed-modules
nano sign-virtual-box
</code></pre>
<p>In the file, paste the following script.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-keyword">for</span> modfile <span class="hljs-keyword">in</span> $(dirname $(modinfo -n vboxdrv))/*.ko; <span class="hljs-keyword">do</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"Signing <span class="hljs-variable">$modfile</span>"</span>
  /usr/src/linux-headers-6.14.0-28-generic/scripts/sign-file sha254 \
                                /root/signed-modules/MOK.priv \
                                /root/signed-modules/MOK.der <span class="hljs-string">"<span class="hljs-variable">$modfile</span>"</span>
<span class="hljs-keyword">done</span>
</code></pre>
<p>Here, the path <code>/usr/src/linux-headers-6.14.0-28-generic/scripts/sign-file</code> should match the output you got before with <code>find /usr/src -name sign-file</code>.</p>
<p>Now run the script after modifying the execution privileges.</p>
<pre><code class="lang-bash">chmod 700 sign-virtual-box
./sign-virtual-box
</code></pre>
<p>This should allow you to now run any virtual machines without any issues.</p>
<h2 id="heading-an-additional-issue">An Additional Issue</h2>
<p>However, I also did run into another issue where I had to run the following command after every reboot to get the virtual machines to run, other than the above fix. This might or might not be the case.</p>
<pre><code class="lang-bash">sudo modprobe -r kvm_intel
</code></pre>
<p>This is used to unload the <code>kvm_intel</code> kernel module, which is a driver that allows the KVM (Kernel-based Virtual Machine) hypervisor to leverage the virtualization extensions found in Intel CPUs. The <code>modprobe -r</code> part of the command specifically tells the system to remove (or unload) the specified module.</p>
<h1 id="heading-reference">Reference</h1>
<ul>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/61248315/sign-virtual-box-modules-vboxdrv-vboxnetflt-vboxnetadp-vboxpci-centos-8">https://stackoverflow.com/questions/61248315/sign-virtual-box-modules-vboxdrv-vboxnetflt-vboxnetadp-vboxpci-centos-8</a></p>
</li>
<li><p><a target="_blank" href="https://askubuntu.com/questions/1537180/modprobe-vboxdrv-could-not-insert-vboxdrv-key-was-rejected-by-service">https://askubuntu.com/questions/1537180/modprobe-vboxdrv-could-not-insert-vboxdrv-key-was-rejected-by-service</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Pixel Graphics Engine - Introduction]]></title><description><![CDATA[So, I was wondering about making a very basic graphics engine… So I made one! The project is called Pixel Graphics Engine. Pixel Graphics Engine is a Processing-based pixel art animation framework. It allows you to create, animate, and interact with ...]]></description><link>https://blog.asankasovis.com/pixel-graphics-engine-introduction</link><guid isPermaLink="true">https://blog.asankasovis.com/pixel-graphics-engine-introduction</guid><category><![CDATA[Graphics Engine]]></category><category><![CDATA[Processing]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Wed, 06 Aug 2025 15:33:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754494167368/fdd371f3-8a18-4439-9ee8-3d7dc76d7965.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So, I was wondering about making a very basic graphics engine… So I made one! The project is called <a target="_blank" href="https://github.com/asankaSovis/Pixel_Graphics_Engine">Pixel Graphics Engine</a>. Pixel Graphics Engine is a <a target="_blank" href="https://processing.org/">Processing</a>-based pixel art animation framework. It allows you to create, animate, and interact with pixel-based sprites on a customizable grid. The engine supports sprite movement, collision detection, animation, and various background effects, making it suitable for pixel art experiments and basic game development.</p>
<h1 id="heading-how-do-you-start-working">How do you start working?</h1>
<ul>
<li><p>Clone the Pixel Graphics Engine repository, or download a release ZIP.</p>
</li>
<li><p>Rename the project to whatever you prefer.</p>
</li>
<li><p>Open the project in Processing.</p>
</li>
<li><p>Edit the code and run.</p>
</li>
</ul>
<p>There’s already placeholder functions provided for ease of development. You can simply replace the dummy code with your own.</p>
<h1 id="heading-development-structure">Development Structure</h1>
<ul>
<li><p>Add Sprites: Modify <code>CreateSprites()</code> in <code>contents.pde</code></p>
</li>
<li><p>Custom Patterns: Create new Pattern objects for different shapes/animations.</p>
</li>
<li><p>Logic: Add game or animation logic in <code>PerformLogic</code></p>
</li>
</ul>
<h1 id="heading-main-components">Main Components</h1>
<ol>
<li><h2 id="heading-pixel-grid">Pixel Grid</h2>
</li>
</ol>
<ul>
<li><p>Resolution: Set via pixel_res (PVector(x, y))</p>
</li>
<li><p>Pixel Size: Set via pixel_size (PVector(x, y))</p>
</li>
<li><p>Offset: Set via pixel_offset (PVector(x, y))</p>
</li>
</ul>
<ol start="2">
<li><h2 id="heading-sprites">Sprites</h2>
</li>
</ol>
<p>Defined in <code>contents.pde</code> Created using the Sprite class (<code>driver.pde</code>) Example: Five ball sprites with random colours and movement</p>
<ol start="3">
<li><h2 id="heading-driver">Driver</h2>
</li>
</ol>
<p>Manages pixel updates, rendering, and sprite interactions See Driver</p>
<ol start="4">
<li><h2 id="heading-animation-amp-patterns">Animation &amp; Patterns</h2>
</li>
</ol>
<p>Sprites use Pattern objects for animation frames Supports rotation, flipping, and key frame control</p>
<ol start="5">
<li><h2 id="heading-custom-logic">Custom Logic</h2>
</li>
</ol>
<p>Add per-frame behaviours in <code>PerformLogic</code></p>
<p>Make sure to mention the Pixel Graph Engine when sharing things you made with it. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[All About Shutting Down Your Computer]]></title><description><![CDATA[Do you think you know how to shut down your Linux computer? Think again! There are more ways in which you can shut down your system than the control panel. All you need is the terminal and sudo privileges. Here’s a break-down of the shutdown command ...]]></description><link>https://blog.asankasovis.com/all-about-shutting-down-your-computer</link><guid isPermaLink="true">https://blog.asankasovis.com/all-about-shutting-down-your-computer</guid><category><![CDATA[Ubuntu]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[desktop]]></category><category><![CDATA[shutdown]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Tue, 29 Jul 2025 15:58:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753804494861/64ccc7d3-63f6-4f35-a7ae-eab706aaaa75.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Do you think you know how to shut down your Linux computer? Think again! There are more ways in which you can shut down your system than the control panel. All you need is the terminal and sudo privileges. Here’s a break-down of the <code>shutdown</code> command in Linux.</p>
<p>The <code>shutdown</code> command in Linux (Bash) is a powerful utility used to safely halt, power off, or reboot the system. It allows administrators to schedule these actions and notify logged-in users. The general structure of this command is as below:</p>
<pre><code class="lang-bash">shutdown [OPTIONS...] [TIME] [MESSAGE]
</code></pre>
<ul>
<li><p><em>[OPTIONS...]</em> - Controls the specific action (halt, power off, reboot) and other behaviours.</p>
</li>
<li><p><em>[TIME]</em> - Specifies when to perform the shutdown. This is often a mandatory argument if you want to specify a message or schedule the shutdown.</p>
</li>
<li><p><em>[MESSAGE]</em> - An optional message to be broadcast to all logged-in users.</p>
</li>
</ul>
<p>Under [OPTIONS...], the shutdown command allows several options for the shutdown process.</p>
<ul>
<li><p><code>-H</code>/<code>--halt</code> - Halts the machine. This stops all CPU functions but leaves the power on.</p>
</li>
<li><p><code>-P</code>/<code>--poweroff</code> - Powers off the machine. This is often the default behaviour if neither <code>-h</code> (legacy option to override the previous command unless the previous command is —halt) nor <code>-r</code> is specified, completely cutting power.</p>
</li>
<li><p><code>-r</code>/<code>--reboot</code> - Reboots the system.</p>
</li>
<li><p><code>-k</code> - Do not actually shut down, power off, or reboot. Instead, just send the wall message to all logged-in users. This is useful for testing scripts or broadcasting warnings without performing the action.</p>
</li>
<li><p><code>-c</code> - Cancels a pending shutdown. This can only be used if a time argument was specified previously to schedule a shutdown. You cannot specify a <code>TIME</code> or <code>MESSAGE</code> with this option.</p>
</li>
<li><p><code>--no-wall</code> - Do not send a wall message before halting, powering off, or rebooting.</p>
</li>
<li><p><code>--show</code> - Shows a pending shutdown action and time if there is any.</p>
</li>
<li><p><code>-t SEC</code> - Tells <code>init</code> (or <code>systemd</code>) to wait <code>SEC</code> seconds between sending warning messages and the kill signal to processes. Defaults to 5 seconds.</p>
</li>
<li><p><code>-f</code> - Skips the file system check (<code>fsck</code>) on the next reboot. Use with caution as it can lead to data inconsistencies if not used properly.</p>
</li>
<li><p><code>-F</code> - Forces the file system check (<code>fsck</code>) on the next reboot. Useful after an unclean shutdown.</p>
</li>
</ul>
<p>Under the [TIME] argument, you can provide a timeout for the shutdown to occur.</p>
<ul>
<li><p><code>now</code> - Triggers an immediate shutdown. This is an alias for <code>+0</code>.</p>
</li>
<li><p><code>+m</code> - Specifies a shutdown in m minutes from now. For example, <code>+10</code> means shutdown in 10 minutes.</p>
</li>
<li><p><code>hh:mm</code> - Specifies an absolute time in 24-hour format. For example, <code>17:30</code> means shutdown at 5:30 PM.</p>
</li>
</ul>
<p>Under [MESSAGE] argument, you can specify a message to be broadcasted to all logged-in users of the device before shutting down.</p>
<p>Here are a few examples with descriptions as to what they do:</p>
<pre><code class="lang-bash">sudo shutdown now
</code></pre>
<blockquote>
<p>Shuts down the system immediately.</p>
</blockquote>
<pre><code class="lang-bash">sudo shutdown -r +5 <span class="hljs-string">"System rebooting for maintenance. Please save your work."</span>
</code></pre>
<blockquote>
<p>Reboots the system in 5 minutes with the message <em>‘System rebooting for maintenance. Please save your work.’</em></p>
</blockquote>
<pre><code class="lang-bash">sudo shutdown -P 23:00
</code></pre>
<blockquote>
<p>Shut down the system at 11:00 PM.</p>
</blockquote>
<pre><code class="lang-bash">sudo shutdown -c
</code></pre>
<blockquote>
<p>Cancel any pending shut-downs.</p>
</blockquote>
<pre><code class="lang-bash">sudo shutdown -k <span class="hljs-string">"The system will not be going down for maintenance."</span>
</code></pre>
<blockquote>
<p>Do not shut down or reboot but only display the message <code>‘The system will not be going down for maintenance.’</code></p>
</blockquote>
<p>It is important to remember that the <code>shutdown</code> command require administrator privileges. Thus, it is important to run the <code>shutdown</code> command with <code>sudo</code>. Although not that important to remember, if a shutdown is scheduled, it sends warning messages to logged-in users, allowing them to save their work. A file <code>/run/nologin</code> is created (usually 5 minutes before the scheduled time) to prevent further logins.</p>
<p>On modern Linux distributions using <code>systemd</code>, <code>shutdown</code> often acts as a compatibility wrapper, internally invoking equivalent <code>systemctl</code> commands (e.g., <code>systemctl poweroff</code>, <code>systemctl reboot</code>, <code>systemctl halt</code>). While <code>systemctl</code> offers more granular control over system states, <code>shutdown</code> remains a convenient and widely used command, especially for scheduled actions.</p>
<p>While shutdown is the most common command, the following aliases are also available to simplify the specific commands:</p>
<pre><code class="lang-bash">reboot
</code></pre>
<p>Simply reboots the system, similar to the command <code>shutdown -r now</code>.</p>
<pre><code class="lang-bash">halt
</code></pre>
<p>Simply halts the system, similar to the command <code>shutdown -H now</code>.</p>
<pre><code class="lang-bash">poweroff
</code></pre>
<p>Simply powers off the system, similar to the command <code>shutdown now</code>.</p>
<p>Other than this, the underlying <code>systemctl</code> provide a lot more options should you choose to use the underlying commands:</p>
<ul>
<li><p><code>sudo systemctl poweroff</code> - Powers off the system immediately.</p>
</li>
<li><p><code>sudo systemctl reboot</code> - Reboots the system immediately.</p>
</li>
<li><p><code>sudo systemctl halt</code> - Halts the system immediately (may or may not power off, depending on system configuration).</p>
</li>
<li><p><code>sudo systemctl suspend</code>: -Puts the system into a low-power state, keeping memory powered (like sleep mode).</p>
</li>
<li><p><code>sudo systemctl hibernate</code> - Saves the system's state to disk and powers off, allowing a full restore upon next boot.</p>
</li>
<li><p><code>sudo systemctl hybrid-sleep</code> - Attempts to suspend to RAM and disk (combines suspend and hibernate).</p>
</li>
</ul>
<p>The <code>systemctl</code> commands are graceful shutdown commands, meaning that they will attempt a graceful shutdown, stopping processes and syncing file systems before the final action. Using <code>-f</code> or <code>--force</code> with any of them can bypass these graceful steps, potentially leading to data loss if not used carefully.</p>
<h1 id="heading-reference">Reference</h1>
<ul>
<li><p><a target="_blank" href="https://man.archlinux.org/man/shutdown.8.en">https://man.archlinux.org/man/shutdown.8.en</a></p>
</li>
<li><p><a target="_blank" href="https://man.archlinux.org/man/reboot.8">https://man.archlinux.org/man/reboot.8</a></p>
</li>
<li><p><a target="_blank" href="https://man.archlinux.org/man/core/systemd-sysvcompat/poweroff.8.en">https://man.archlinux.org/man/core/systemd-sysvcompat/poweroff.8.en</a></p>
</li>
<li><p><a target="_blank" href="https://man.archlinux.org/man/halt.8">https://man.archlinux.org/man/halt.8</a></p>
</li>
<li><p><a target="_blank" href="https://man.archlinux.org/man/systemctl.1">https://man.archlinux.org/man/systemctl.1</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Creating Bootable Windows ISOs on Linux]]></title><description><![CDATA[Recently, I had to create a bootable Windows pen drive for a friend. As a Linux user, I found that the typical tools we use to create bootable pen drives for Linux, like Disks and Impression, does not work on Windows ISOs. Tools like Rufus that work ...]]></description><link>https://blog.asankasovis.com/creating-bootable-windows-isos-on-linux</link><guid isPermaLink="true">https://blog.asankasovis.com/creating-bootable-windows-isos-on-linux</guid><category><![CDATA[Windows]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Ubuntu]]></category><category><![CDATA[ISO]]></category><category><![CDATA[Installation]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Wed, 16 Jul 2025 15:36:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752680121324/23fbc3db-4edb-44c1-a1cd-7a5ffc7945be.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently, I had to create a bootable Windows pen drive for a friend. As a Linux user, I found that the typical tools we use to create bootable pen drives for Linux, like <a target="_blank" href="https://gitlab.gnome.org/GNOME/gnome-disk-utility">Disks</a> and <a target="_blank" href="https://apps.gnome.org/Impression/">Impression</a>, does not work on Windows ISOs. Tools like <a target="_blank" href="https://rufus.ie/en/">Rufus</a> that work on Windows, doesn’t work on Linux, so I had to look into other alternatives. The only option that I found, other than creating a Windows VM, is the <a target="_blank" href="https://woeusb.com/#faq">WOEUSB tool</a>.</p>
<p>The WOEUSB tool managed to create a bootable Windows pen drive with minimal effort. It is developed specifically for this purpose, and it manages to do it really well. This quick article will guide you on creating a Windows ISO on Linux using WOEUSB.</p>
<h1 id="heading-downloading-an-iso">Downloading an ISO</h1>
<p>It is important to download a valid Windows ISO. They can be found through Microsoft’s official website. Given below are quick links to download Windows ISOs. Note that Microsoft might change these URLs.</p>
<ul>
<li><p><a target="_blank" href="https://www.microsoft.com/en-us/software-download/windows11">Windows 11</a></p>
</li>
<li><p><a target="_blank" href="https://www.microsoft.com/en-us/software-download/windows10ISO">Windows 10</a></p>
</li>
</ul>
<h1 id="heading-installing-woeusb-tool">Installing WOEUSB Tool</h1>
<p>First you need to install the required libraries.</p>
<pre><code class="lang-bash">sudo apt install git p7zip-full python3-pip python3-wxgtk4.0 grub2-common grub-pc-bin parted dosfstools ntfs-3g
</code></pre>
<p>Next, we can install the WOEUSB tool through Python.</p>
<pre><code class="lang-bash">sudo pip3 install WoeUSB-ng --break-system-packages
</code></pre>
<p>Next, we will clone the WOEUSB Repo.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/WoeUSB/WoeUSB-ng.git
<span class="hljs-built_in">cd</span> WoeUSB-ng
</code></pre>
<p>After this, we can run the tool from the terminal.</p>
<pre><code class="lang-bash">./WoeUSB/woeusbgui
</code></pre>
<p>It will ask for the admin password, which should be provided. In certain cases, WOEUSB will immediately close after first install, stating that policy is updated. In this case, you have to open it again using the same command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752678665343/c3696404-cb3c-497e-987a-52bb57a311b4.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-creating-the-iso">Creating the ISO</h1>
<p>Select ‘<em>From a disk image (iso)</em>’ and use the file picker to choose your downloaded ISO. Select the target device under ‘<em>Target device</em>’ and click on ‘<em>Install</em>’. A warning will pop up for confirmation. Make sure that you’ve selected the correct device from the Target devices. Also note that the device will be completely wiped. If you’re OK with this, click on ‘<em>Yes</em>’ to start the process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752679059545/bd6d62dd-2867-4817-bc23-138c600f057a.png" alt class="image--center mx-auto" /></p>
<p>This will start the installation process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752679106258/b43d43b3-3eaa-45ed-806d-2e1d53f5abdd.png" alt class="image--center mx-auto" /></p>
<p>Once installation is done, you will see an ‘<em>Installation Successful</em>’ Message.</p>
<p>Remove the installation media from your computer and use it to install Windows.</p>
<h1 id="heading-uninstalling-woeusb">Uninstalling WOEUSB</h1>
<p>WOEUSB can be uninstalled using the following commands.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ..
rm -rf ./WoeUSB-ng/
sudo pip3 uninstall WoeUSB-ng --break-system-packages
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752679550664/7f508f3b-b716-4455-96e3-a5d11e0eeb73.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>While it is hard to create a Windows installation media on Linux, it is not impossible. With the use of WOEUSB, we can relatively easily create a Windows installation media. The steps outlined in this article will be quite helpful in this matter.</p>
]]></content:encoded></item><item><title><![CDATA[The Call Stack - Hidden Foundation of Functional Programming]]></title><description><![CDATA[In computer science, the stack is an important concept. In reality also, the stack is a crucial part of the execution of an assembly program written in a higher-level language. From clicking a button on screen to sending a payload to space, the conce...]]></description><link>https://blog.asankasovis.com/the-call-stack-hidden-foundation-of-functional-programming</link><guid isPermaLink="true">https://blog.asankasovis.com/the-call-stack-hidden-foundation-of-functional-programming</guid><category><![CDATA[Computer Science]]></category><category><![CDATA[#StackDataStructure]]></category><category><![CDATA[stack memory]]></category><category><![CDATA[explained]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Tue, 08 Jul 2025 16:56:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751993551796/db426b29-1dc6-46ee-96bb-dddf842de956.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In computer science, the stack is an important concept. In reality also, the stack is a crucial part of the execution of an assembly program written in a higher-level language. From clicking a button on screen to sending a payload to space, the concept of a stack plays a major part. Pioneered and popularized by brilliant minds like Edsger Dijkstra in the mid-20th century, it provided a robust and efficient way for compilers to handle memory and control.</p>
<p>Let's start with the concept of a stack. Imagine a stack of plates in your house: you can only add a new plate to the top, and you can only take the top plate off. This "Last-In, First-Out" (LIFO) principle is how the stack works. In your computer, a similar thing happens every time you call a new function, declare a variable, or return from a function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751984819945/b22a52dc-9c92-456a-b3d0-c7af58e22a9c.jpeg" alt="A stack of plates [AI generated]" class="image--center mx-auto" /></p>
<blockquote>
<p>A stack of plates [AI generated]</p>
</blockquote>
<p>We can visualize the memory as a tall shelf with thousands of tiny drawers that can hold a 'byte' of data. Now, it is important to manage this memory efficiently to take the best out of the system and to mitigate mistakes. This is where memory management comes into play.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751986707076/9f5d1cf9-08c8-4d7b-a124-eca254ca7754.jpeg" alt="A stack of drawers [AI generated]" class="image--center mx-auto" /></p>
<blockquote>
<p>A stack of drawers [AI generated]</p>
</blockquote>
<p>The Stack, in the sense of computer memory management, is one such strategy. Now think of the plate analogy we discussed before, and the assign the same ruleset to the tall 'memory' shelf. You have to start from the bottom most drawer. You can only put a 'byte' into the drawer above the one last filled. And you can only take the topmost one at a time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751987770307/a71b99b7-388f-4151-aa8d-efd2e0ac3d96.png" alt="Typical SRAM structure of the ARM memory" class="image--center mx-auto" /></p>
<blockquote>
<p>Typical SRAM structure of the ARM memory</p>
</blockquote>
<p>Just like that, the memory allocated to the stack is only accessible in the above discussed way. Think of the stack as a dedicated workspace for managing critical information. The stack is crucial to handle:</p>
<ul>
<li><p>Function Calls: Every time a function is called, its details are 'pushed' onto the stack. When the function finishes, its information is 'popped' off.</p>
</li>
<li><p>Local Variables: The temporary data a function needs to do its job is stored right there on the stack.</p>
</li>
<li><p>Program Flow: It's the stack that ensures your program returns to the exact spot it left off after completing a task or jumping to a different part of the code.</p>
</li>
</ul>
<p>Now we will see how the Stack works. In real memory, the stack starts from the highest available memory address and move down. To further understand how the stack behaves, we will use a sample C code as an example.</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">square</span><span class="hljs-params">(<span class="hljs-keyword">int</span> num)</span> </span>{
    <span class="hljs-keyword">int</span> result = num * num;
    <span class="hljs-keyword">return</span> result;
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">int</span> x = <span class="hljs-number">2</span>;
    square(x);
}
</code></pre>
<p>The compiled x86-64 Clang Assembly code is as below.</p>
<pre><code class="lang-plaintext">square:
    push rbp
    mov rbp, rsp
    mov dword ptr [rbp - 4], edi
    mov eax, dword ptr [rbp - 4]
    imul eax, dword ptr [rbp - 4]
    mov dword ptr [rbp - 8], eax
    mov eax, dword ptr [rbp - 8]
    pop rbp
    ret

main:
    push rbp
    mov rbp, rsp
    sub rsp, 16
    mov dword ptr [rbp - 4], 2
    mov edi, dword ptr [rbp - 4]
    call square
    xor eax, eax
    add rsp, 16
    pop rbp
    ret
</code></pre>
<p>If you analyse the code, every time we switch functions, we're pushing the Base Pointer (RBP) onto the stack. Then we change the RBP to the current Stack Pointer (RSP). This way, we know where to return to after the function executes and returns. On the other hand, we create space for all the local variables of that function within the stack as soon as we're done with it. After execution, the stack pops all of that data and move back to where we started.</p>
<p>This is better visualized in the below animation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751903741545/b5ad6073-4a32-4ca3-8488-101e825ddd2a.gif" alt class="image--center mx-auto" /></p>
<p>From the simplest script to the most complex operating system, the stack is silently working behind the scenes, ensuring that our digital world runs smoothly and predictably. It's a testament to how some of the most powerful and enduring ideas in computing are rooted in simple, yet effective, abstractions.</p>
<p>Reference:</p>
<ul>
<li><p>Wikipedia article on the Stack data type: <a target="_blank" href="https://en.wikipedia.org/wiki/Stack_\(abstract_data_type\)">https://en.wikipedia.org/wiki/Stack_(abstract_data_type)</a></p>
</li>
<li><p>Wikipedia article on the Call Stack: <a target="_blank" href="https://en.wikipedia.org/wiki/Call_stack">https://en.wikipedia.org/wiki/Call_stack</a></p>
</li>
<li><p>Code sample on Compiler Explorer: <a target="_blank" href="https://godbolt.org/z/1vddacPM3">https://godbolt.org/z/1vddacPM3</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Easy Steps to Create Your Development Environment]]></title><description><![CDATA[Setting up the development environment for your requirements is pretty straightforward. nRF provides an intuitive and easy-to-use development environment that is easy to set up and develop programs with. First, we will start our development journey b...]]></description><link>https://blog.asankasovis.com/easy-steps-to-create-your-development-environment-nrf-toolchain</link><guid isPermaLink="true">https://blog.asankasovis.com/easy-steps-to-create-your-development-environment-nrf-toolchain</guid><category><![CDATA[Nordic Semiconductor]]></category><category><![CDATA[toolchain]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sat, 22 Mar 2025 18:30:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742632556210/efbdf1da-6421-4272-872a-0c33bf87e359.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Setting up the development environment for your requirements is pretty straightforward. nRF provides an intuitive and easy-to-use development environment that is easy to set up and develop programs with. First, we will start our development journey by setting up the nRF development environment. I will be using Ubuntu 23.10 but any version above 22.04 will be more or less the same. For Windows, though I ran into a bunch of errors while setting up so I recommend setting up an Ubuntu environment such as WSL in Windows.</p>
<h1 id="heading-installing-the-nrf-connect-for-desktop-application">Installing the nRF Connect for Desktop Application</h1>
<p>The first thing is to install the <a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop">nRF Connect for Desktop</a> application. Go to the <a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop/Download#infotabs">Downloads</a> section. First of all, download the latest package for your preferred operating system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703562048021/fd55b409-c112-4672-bc81-46c1d0415883.png" alt="Download page for nRF Commect for Desktop application" class="image--center mx-auto" /></p>
<p>For Windows, the application comes as an exe installer. Simply double-clicking the downloaded exe and following the given instructions will be ideal. For Linux though, the application comes as an AppImage. AppImage is a packaging format which bundles all the dependencies and libraries as one single executable which can just be run by double-clicking. However, the AppImage version that Nordic has used to bundle the application is outdated and for modern systems, just double-clicking will not help. In such a case, I'd recommend you follow this tutorial to set up the application. Even if it works for you, this method will be faster and more reliable as it sets up the program to run without mounting itself. <mark>DO NOT ATTEMPT TO INSTALL </mark> <code>libfuse2</code><mark>as it WILL BREAK YOUR SYSTEM</mark>.</p>
<p>Now that we have the nRF Connect for Desktop ready, we can open the application by double-clicking the AppImage or from the app launcher. This will open the nRF Connect for Desktop application.</p>
<h1 id="heading-installing-a-preferred-toolchain">Installing a Preferred Toolchain</h1>
<p>The next important thing to do is the install the preferred toolchain. In the Apps tab of the nRF Connect, you will find an entry called Toolchain Manager. Toolchain Manager allows you to manage the different toolchains we need for microcontroller development. We will start by installing the Toolchain Manager. Click on the Install button next to the Toolchain Manager entry and wait for the entry to complete the installation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703587376660/9890b137-44c6-400c-86fb-090c59603088.png" alt="nRF Connect for Desktop application" class="image--center mx-auto" /></p>
<p>If the installation succeeds, the Install button will be replaced by an Open button. Click on the Open button to open the Toolchain Manager. Now we will install a preferred toolchain. It's suggested to install the latest toolchain available unless you have a specific reason to use another version. To do this, click on the Install button as usual. This will prompt a small window asking you to confirm the install directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703587685961/a1a548ed-1cfa-4498-9e83-a863b82d9ca8.png" alt="Message prompting to select the toolchain installation directory" class="image--center mx-auto" /></p>
<p>The default path would be the ideal location to leave the toolchains however, if you want to install in a different location, you can click on the Change directory button and choose the location. Note that once installed, changing the toolchain location will be hard, so choose the proper place to install your toolchain. Once complete, click on Continue installation to install the selected toolchain. Installing a toolchain will take a considerable amount of time depending on your hardware and network connection. Once complete, you will get a window similar to below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703587938558/a242e44e-074a-4578-adfe-43f341b28d5b.png" alt="Toolchain Manager application" class="image--center mx-auto" /></p>
<h1 id="heading-installing-the-vs-code-editor">Installing the VS Code Editor</h1>
<p>For development, nRF Connect supports the VS Code code editor. If you already have VS Code installed, you can continue with installing the extensions. However, if you don't have VS Code installed, you can install it by downloading the package from the <a target="_blank" href="https://code.visualstudio.com/download">official website</a>. It is recommended to use the official website to install VS Code rather than other methods like Flatpaks or 3rd party websites. The installation method should be pretty typical and does not need any explanation.</p>
<h1 id="heading-installing-the-nrf-command-line-tools">Installing the nRF Command Line Tools</h1>
<p>Once VS Code is done installing, you can click on the Open VS Code button that appears after the installation of the toolchain. However, this will prompt a message asking you to install <a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download">nRF Command Line Tools</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703588715346/4fc24286-ef68-41ea-a7c4-611411a078e7.png" alt="Install nRF Command Line Tools" class="image--center mx-auto" /></p>
<p>Click on the provided link to open the download location. From the website, download the correct installer for your preferred operating system. As usual, the installation will be typical and you can follow the instructions provided. For Windows, it will be a standard installer as an exe while for Linux, it will be a deb file.</p>
<h1 id="heading-installing-the-environment-variables">Installing the Environment Variables</h1>
<p>It is a good practise to also setup the required environment variables for the development to go smoothly. For this, in the Toolchain Manager, click on the drop down button next to Open VS Code button. This will show multiple options that include Generate environment script.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703590504077/7356d229-2871-4dcb-8f9b-1d4ddca2157c.png" alt="Installing environment variables" class="image--center mx-auto" /></p>
<p>Clicking on this will prompt you to select a place to save the generated script. Save it anywhere you want and navigate to that location with your file explorer. For Windows, this will create a cmd file that can be double-click to install. Provide the Administrator password if prompted. For Linux, you can right-click in the file explorer and click on Open in Terminal. This will open a terminal window with the path as the directory in which you have the bash script file. Enter the below two commands to run this script.</p>
<pre><code class="lang-bash">chmod +x ./env.sh
./env.sh
</code></pre>
<p>This will install the environment variables in the operating system. It is recommended to restart your operating system before proceeding with the next steps.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703590818519/e073de38-5142-45a5-82a1-65d02b5e95db.png" alt="Installing environment variables" class="image--center mx-auto" /></p>
<h1 id="heading-setting-up-the-vs-code-development-environment-for-nrf">Setting up the VS Code Development Environment for nRF</h1>
<p>Once complete, it is recommended to restart the operating system before proceeding. Now you can open the toolchain manager again and click on Open VS Code. Now you will see a new message asking you to install the VS Code extensions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703589199445/d40d1715-ea2f-42e9-afbe-60ca146c5901.jpeg" alt="Installing VS Code extensions" class="image--center mx-auto" /></p>
<p>Clicking on Install missing extensions button will install all the extensions one by one. Once all the installations are complete, you can click on Open VS Code again to open the VS Code editor. This will open the VS Code where you can start your development. On how to start development, you can refer to this link.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703589427237/643a2d3a-0277-4796-99ef-029b4e820b3d.png" alt="VS Code after setting up nRF Toolchain" class="image--center mx-auto" /></p>
<h1 id="heading-fixing-the-jlinkarm-dll-load-failed-error">Fixing the JLinkARM DLL load failed Error</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703589523191/5e5d51cf-2fb1-4d51-bace-d96dd6ded2f3.png" alt="Fixing the JLinkARM DLL load failed Error" class="image--center mx-auto" /></p>
<p>Sometimes when trying to flash the code to your Nordic device, you might end up with an error that looks like above. In this case, the issue might be an out-of-date JLink driver installed. Go to the <a target="_blank" href="https://www.segger.com/downloads/jlink/">SEGGER JLink download page</a> and download the latest driver for your operating system. As usual, the installation is straightforward and does not need any explanation. Once done, the Flashing should work as expected.</p>
<p>The nRF development environment is a powerful and versatile ecosystem for creating applications for Nordic Semiconductor's nRF series of low-power wireless SoCs. It caters to developers of all skill levels, offering options for both beginners and seasoned professionals. So enjoy coding with your new nRF development board.</p>
<h1 id="heading-references">References</h1>
<ul>
<li><p><a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop/Download#infotabs">nRF Connect for Desktop download page</a></p>
</li>
<li><p><a target="_blank" href="https://code.visualstudio.com/download">VS Code download page</a></p>
</li>
<li><p><a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download">nRF Command Line Tools download page</a></p>
</li>
<li><p><a target="_blank" href="https://www.segger.com/downloads/jlink/">SEGGER JLink tool download page</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Introduction]]></title><description><![CDATA[The nRF development environment is a powerful and user-friendly platform that makes creating innovative and low-power wireless applications with Nordic SoCs easy. So, whether you're a seasoned developer or just starting, the nRF ecosystem has somethi...]]></description><link>https://blog.asankasovis.com/introduction-nrf-toolchain</link><guid isPermaLink="true">https://blog.asankasovis.com/introduction-nrf-toolchain</guid><category><![CDATA[Nordic Semiconductor]]></category><category><![CDATA[toolchain]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sat, 22 Mar 2025 08:28:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742631596266/b29c5086-18d5-441b-a809-da3d5f18fe7f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The nRF development environment is a powerful and user-friendly platform that makes creating innovative and low-power wireless applications with Nordic SoCs easy. So, whether you're a seasoned developer or just starting, the nRF ecosystem has something to offer you. It’s primarily centred around Nordic Semiconductor's nRF series of System-on-Chips (SoCs) and is designed to facilitate the creation of wireless applications, particularly those utilizing Bluetooth Low Energy (BLE) and other low-power wireless technologies. It features the following components:</p>
<ul>
<li><p><strong>nRF Series SoCs:</strong> These are the core of the development environment. Nordic Semiconductor offers a range of nRF chips (like the nRF51, nRF52, nRF53, and nRF91 series), each with varying capabilities in terms of processing power, wireless protocol support, and features. These SoCs are designed for low-power operation, making them ideal for battery-powered IoT devices.</p>
</li>
<li><p><strong>nRF Connect SDK (Software Development Kit):</strong> This is a crucial software tool for developing applications for nRF devices. It provides a comprehensive set of tools, libraries, and examples for building firmware. The nRF Connect SDK is based on the Zephyr RTOS (Real-Time Operating System), which offers a robust and scalable platform for embedded development.</p>
</li>
<li><p><strong>nRF Connect for Desktop:</strong> This is a PC-based application that provides various tools for testing, programming, and debugging nRF devices.</p>
</li>
<li><p><strong>nRF Connect for VS Code:</strong> This Visual Studio Code extension streamlines nRF Connect SDK development within the popular VS Code IDE. It simplifies tasks like building, flashing, and debugging.</p>
</li>
<li><p><strong>Development Kits (DKs):</strong> Nordic Semiconductor provides development kits that allow developers to prototype and test their applications. These kits typically include an nRF SoC, along with other necessary components.</p>
</li>
</ul>
<p>The reason for starting this article series is to share the knowledge I received about the nRF development flow. Sometimes it can get overwhelming to enter into the nRF toolchain because of the lack of sources online. However, I can recommend the <a target="_blank" href="https://academy.nordicsemi.com/">Nordic Dev Academy</a> as it is a good starting point for further information on the Nordic toolchain and SDKs.</p>
]]></content:encoded></item><item><title><![CDATA[Making Your Own Website for Free]]></title><description><![CDATA[Having your own website can be an advantage, whether you’re a small business owner, a freelancer, or even a student. A personal website will allow you to stand out from the rest of the crowd while giving you the freedom to express yourself however yo...]]></description><link>https://blog.asankasovis.com/making-your-own-website-for-free</link><guid isPermaLink="true">https://blog.asankasovis.com/making-your-own-website-for-free</guid><category><![CDATA[website]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sun, 16 Mar 2025 17:01:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742630610459/86dd3ace-bad4-4915-ac3a-4ea8a802a94a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Having your own website can be an advantage, whether you’re a small business owner, a freelancer, or even a student. A personal website will allow you to stand out from the rest of the crowd while giving you the freedom to express yourself however you want. However, most people don’t consider making their own personal website, sometimes due to a lack of time, money or even technical know-how. But the thing is, there are modern ways to make a website quickly and efficiently, so it doesn’t matter what technical background you have.</p>
<h1 id="heading-making-the-website-itself">Making the Website Itself</h1>
<p>There are multiple ways to make a website. You can use <a target="_blank" href="https://wordpress.com/">WordPress</a>, download a website from the internet or even make one yourself from scratch. If you want to go with WordPress, you can follow the <a target="_blank" href="https://wordpress.com/go/">online resources</a> and get a working website up quickly. If you prefer to develop your own website from scratch, it might be a bit more complicated; I’d suggest you go on this route only if you know what you’re doing. An easy way is to download a sample website from the internet. There are great sites like <a target="_blank" href="http://www.free-css.com">www.free-css.com</a>. Simply download one and modify it according to your liking.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742135955511/61d42fd1-00d6-4bd0-ac73-7cf026d70d94.png" alt="www.free-css.com website" class="image--center mx-auto" /></p>
<h1 id="heading-hosting-the-website">Hosting the Website</h1>
<p>This is where most people get confused. While there are so many hosting providers - <a target="_blank" href="https://azure.microsoft.com/en-us/">Microsoft Azure</a>, <a target="_blank" href="https://firebase.google.com/">Google Firebase</a>, <a target="_blank" href="https://aws.amazon.com/">Amazon AWS</a>, <a target="_blank" href="https://www.hostinger.com/">Hostinger</a>, etc, there’s one hosting provider that you might not be considered or even know about: <a target="_blank" href="https://github.com/">GitHub</a>. That’s right, you can host your personal website on Github with little to no effort, costing zero money.</p>
<p>What you have to do is go to your GitHub account and create a new repository. This repository should be named <strong><em>&lt;your-github-name&gt;.github.io</em></strong>. Here <em>&lt;your-github-name&gt;</em> refers to your Github profile name. For example, my GitHub name is <a target="_blank" href="https://github.com/asankaSovis">asankaSovis</a>, so I have my repository titled <a target="_blank" href="https://github.com/asankaSovis/asankaSovis.github.io"><strong><em>asankaSovis.github.io</em></strong></a><strong>.</strong> Make sure that the repository is <strong>Public</strong>. You can choose to initialize the repo with a README, add a .gitignore file or even choose a license; it doesn’t matter.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742136740163/12c79d76-0557-497f-ae63-12018a20d1df.png" alt="Creating a new repository on Github with asankaSovis.github.io as the Repository name (Note that I already have this repository created)" class="image--center mx-auto" /></p>
<p>Once the repository is created, you can clone the repo to your computer. For this, you can use the <strong>Code &gt; Clone &gt; HTTPS</strong> option as below. Under this, click on the copy button to copy the URL and paste it into your terminal with the below command. Note that <em>&lt;URL&gt;</em> refers to the URL that we copied before.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> &lt;URL&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742137230199/f8208498-0460-4aae-bbd6-96869618bb16.png" alt="Clone URL under the git repo." class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742137242228/3546a992-ebc3-4fe3-adb9-67d00e281394.png" alt="Cloning the Github repo." class="image--center mx-auto" /></p>
<p>If you’re using Mac or Linux, you will have <a target="_blank" href="https://git-scm.com/">Git</a> installed by default, so providing the above command would be sufficient. If you’re using Windows, you might need to <a target="_blank" href="https://git-scm.com/downloads">install Git</a>. Refer to the <a target="_blank" href="https://git-scm.com/doc">official documentation</a> for how you can install Git. Also, you have to make sure that Git is initialized with your GitHub username and password. Refer to the <a target="_blank" href="https://git-scm.com/docs/gittutorial">Github documentation</a> for this.</p>
<p>Once cloned, open the directory in your file browser. Copy your website to this directory while making sure that the <em>index.html</em> file is at the root of this cloned directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742137523270/7c4a288a-dd0c-412c-ad5c-cdb0d6972b0b.png" alt="Cloned directory with the contents of the website. Note the index.html in the root of this directory." class="image--center mx-auto" /></p>
<p>Now, we have to commit the changes and sync the changes to the source. To do this, you can use the following commands in order.</p>
<pre><code class="lang-bash">git add .
git commit -m <span class="hljs-string">"Initial Commit"</span>
git push &amp;&amp; git pull
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742137866272/1e26d5d1-228b-46fa-b90a-2d5b6c96a82b.png" alt="Committing the website to Github." class="image--center mx-auto" /></p>
<p>Now if you open the GitHub repo on your browser, you will see a yellow dot in the interface. Clicking on this will reveal the status of publishing your website. When this yellow dot turns into a green checkmark, the website is online.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742138060599/151ee5b1-62fd-4d36-b423-aa94ffae55f8.png" alt="Completed deploying of the website." class="image--center mx-auto" /></p>
<p>That’s it, your website is now online. Visiting the <strong><em>&lt;your-github-name&gt;.github.io</em></strong> website will reveal your very own personal website. Here <em>&lt;your-github-name&gt;</em> refers to your Github profile name, as mentioned before.</p>
<h1 id="heading-adding-our-own-custom-domain">Adding Our Own Custom Domain</h1>
<p>You don’t have to stop here; you can host the website on your own URL as well, with no need for the <strong><em>&lt;your-github-name&gt;.github.io</em></strong> URL at all. To do this, we need our very own domain, and it will cost you a bit. You can use any domain provider: <a target="_blank" href="https://www.godaddy.com/en-in">GoDaddy</a>, <a target="_blank" href="https://www.hostinger.com/domain-name-search">Hostinger</a>, <a target="_blank" href="https://www.bluehost.com/">Bluehost</a>, etc. Here, I will be using <a target="_blank" href="https://www.namecheap.com/">Namecheap</a>.</p>
<p>Visit the Namecheap website and create your account. After logging back into your account, go to the homepage. Here, you can search for whatever domain name you want.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742138565431/1786d900-27d0-475f-b611-e1e17935e7eb.png" alt="Namecheap website with the domain search open." class="image--center mx-auto" /></p>
<p>Once you search for a name for your domain, Namecheap will show you a list of domains available for your purchase. Double-check carefully and choose a domain that suits you well. You must consider the intended audience, initial cost, yearly payment, etc. when you buy a domain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742138740375/432289d0-bd83-4fee-8e62-1ec35d3d8c00.png" alt="Namecheap search results." class="image--center mx-auto" /></p>
<p>Once you have the right domain, add it to the cart, go to checkout and buy it. You will need to provide your card details at checkout. After you complete your transaction, go to <strong>Your Account &gt; Dashboard</strong> to view the newly registered domain. Under <strong>Dashboard &gt; Recently Active in Your Account</strong>, you will see the domain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742139238514/5e1b8989-5f9b-489a-8526-4aed48cfad2e.png" alt="Registered domain under Dashboard." class="image--center mx-auto" /></p>
<p>Click on <strong>Manage,</strong> and under this, you have to click on <strong>Advanced DNS</strong>. Here, add the following under <strong>Host Records</strong>. You can use the <strong>ADD NEW RECORD</strong> button.</p>
<pre><code class="lang-plaintext">A Record         @        185.199.108.153                30 min
A Record         @        185.199.109.153                Automatic
A Record         @        185.199.110.153                Automatic
A Record         @        185.199.111.153                Automatic
CNAME Record     www    &lt;your-github-name&gt;.github.io.    Automatic
</code></pre>
<p>Once this is done, go to your website’s Github repository again. Here, go to <strong>Settings &gt; Pages &gt; Custom Domain</strong>. In the textbox, enter the domain you just registered. Under this, a yellow dot will appear, followed by a text that reads <em>‘DNS Check in Progress. ’</em> Wait for a few minutes and if all is well, this will turn into a green tick mark followed by a text that reads <em>‘DNS check successful’</em>. If not, review the steps again to see if you have followed everything correctly. Sometimes, it will take several hours for domains to start working correctly, so consider giving it some time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742140067579/9c86fedc-e03c-43a9-98da-28fef90d3b34.png" alt="Custom domain option under Settings in the Github repo of the website." class="image--center mx-auto" /></p>
<p>Now if you visit your domain on your browser, you will see your website hosted. The following variations of the URL will be working as expected.</p>
<pre><code class="lang-plaintext">http://&lt;your-domain&gt;.&lt;TLD-domain&gt;
http://www.&lt;your-domain&gt;.&lt;TLD-domain&gt;
https://&lt;your-domain&gt;.&lt;TLD-domain&gt;
https://www.&lt;your-domain&gt;.&lt;TLD-domain&gt;
&lt;your-domain&gt;.&lt;TLD-domain&gt;
www.&lt;your-domain&gt;.&lt;TLD-domain&gt;
</code></pre>
<p>Here, <em>&lt;your-domain&gt;</em> refers to your registered domain and the <em>&lt;TLD-domain&gt;</em>. refers to the Top Level Domain (TLD) you registered it under. For example, .com, .org, .it, etc.</p>
<h1 id="heading-extending-the-domain-to-your-hashnode-blog">Extending the Domain to Your Hashnode Blog</h1>
<p>If you have an active blog in <a target="_blank" href="https://hashnode.com/">Hashnode</a>, you can do the same thing to host your blog under your custom domain. Go to your Hashnode profile and go to the dashboard of your blog. Under <strong>Blog Dashboard &gt; Domain</strong>, you will find the required settings. Click on <strong>Custom domain</strong> and in the text box, enter a variant of <em>&lt;sub-domain&gt;.&lt;your-domain&gt;.&lt;TLD-domain&gt;</em>. A good option would be <em>blog.&lt;your-domain&gt;.&lt;TLD-domain&gt;</em>. Click on <strong>Add domain</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742140888573/05e57e36-90f3-4dec-8b0f-6b109cde56f7.png" alt="Adding custom domain under Hashnode." class="image--center mx-auto" /></p>
<p>Now you have to go back to you Namecheap Dashboard, and update the <strong>Host Records</strong> again as we did before to include the blog URL as well.</p>
<pre><code class="lang-plaintext">A Record         @        185.199.108.153                30 min
A Record         @        185.199.109.153                Automatic
A Record         @        185.199.110.153                Automatic
A Record         @        185.199.111.153                Automatic
CNAME Record     www    &lt;your-github-name&gt;.github.io.    Automatic
CNAME Record     blog    hashnode.network.               Automatic
</code></pre>
<p>Once updated, you can visit the Hashnode settings page we were in before and it should show a green check mark followed by <strong>Valid</strong> under the <strong>Status</strong> tab as below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742141249080/edf8e0b8-2a39-4ba6-864f-fc8fc22ac382.png" alt="Status shown as Valid under Domain settings in Hashnode." class="image--center mx-auto" /></p>
<p>This indicates that the new domain is ready to be used. Visiting <em>blog.&lt;your-domain&gt;.&lt;TLD-domain&gt;</em> or whatever you chose before will show your Hashnode blog. If not, review the steps again to see if you have followed everything correctly. Sometimes, it will take several hours for domains to start working correctly, so consider giving it some time.</p>
<h1 id="heading-create-redirects-to-your-socials">Create Redirects to Your Socials</h1>
<p>We do not have to end there. You can also create redirects to your social media as well using your custom domain. To do this, instead of <strong>Advanced DNS</strong>, go to <strong>Domain</strong> under your Domains List in Namecheap like we did for the personal website. Here, under <strong>Redirect Domain</strong>, you can set URLs to redirect from your domain. For example, let’s say you want the URL <em>facebook.&lt;your-domain&gt;.&lt;TLD-domain&gt;</em> to automatically redirect to your Facebook profile, simply click on <strong>ADD REDIRECT</strong> and enter <em>facebook.&lt;your-domain&gt;.&lt;TLD-domain&gt;</em> as the Source URL and the URL to your Facebook profile under Destination URL. Now if you visit, <em>facebook.&lt;your-domain&gt;.&lt;TLD-domain&gt;</em>, the URL will be automatically forwarded to your Facebook profile. You can add as many redirects as you want like this.</p>
<h1 id="heading-create-custom-email-redirects">Create Custom Email Redirects</h1>
<p>Another awesome feature you will get is the option to redirect emails. No need to use your personal email to advertise yourself. You can create your email address using your domain. Note that this will not be a brand-new email address but rather a <em>forwarding</em> email address. You will still need a proper email address set up to receive emails.</p>
<p>Under the same setting <strong>Domain</strong> we were in before, go to <strong>Redirect Email</strong>. Here, click on <strong>ADD FORWARDER</strong> and add an alias under <strong>Alias</strong> and your email address under <strong>Forward to</strong>. An alias could be, for example, contact, hello, or enquiries. Let’s say you entered ‘<em>contact’</em> as an alias. Any emails sent to <em>contact@&lt;your-domain&gt;.&lt;TLD-domain&gt;</em> will be forwarded to the personal email you entered under <strong>Forward to</strong>. You can add as many aliases to as many emails as you want like this.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Having your own website is important to increase your reach and advertise yourself as an individual on this ever-expanding internet. Here, I discussed a way you can make your small home in this vast network. On the other hand, buying your domain will also have its advantages, as we discussed. So, make the best out of this great opportunity.</p>
<h1 id="heading-reference">Reference</h1>
<ul>
<li><p>Github Homepage: <a target="_blank" href="https://github.com/">https://github.com/</a></p>
</li>
<li><p>Namecheap Homepage: <a target="_blank" href="https://www.namecheap.com/">https://www.namecheap.com/</a></p>
</li>
<li><p>Hashnode Homepage: <a target="_blank" href="https://hashnode.com/">https://hashnode.com/</a></p>
</li>
<li><p>Git Homepage: <a target="_blank" href="https://git-scm.com/">https://git-scm.com/</a></p>
</li>
<li><p>Git Documentation: <a target="_blank" href="https://git-scm.com/doc">https://git-scm.com/doc</a></p>
</li>
<li><p>Git Tutorials: <a target="_blank" href="https://git-scm.com/docs/gittutorial">https://git-scm.com/docs/gittutorial</a></p>
</li>
<li><p>Configuring a custom domain for your GitHub Pages site: <a target="_blank" href="https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site">https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site</a></p>
</li>
<li><p>How to Map a Custom Domain?: <a target="_blank" href="https://docs.hashnode.com/help-center/blog-domain/how-to-map-a-custom-domain">https://docs.hashnode.com/help-center/blog-domain/how-to-map-a-custom-domain</a></p>
</li>
<li><p>Free CSS: <a target="_blank" href="https://www.free-css.com/">https://www.free-css.com/</a></p>
</li>
<li><p>WordPress Builder: <a target="_blank" href="https://wordpress.com/go/">https://wordpress.com/go/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Wallpaper Slideshows on Linux]]></title><description><![CDATA[So, I was binge-watching YouTube videos and a random thought came to my mind, like most people: What if I write a bash script to change the wallpaper every minute? I will be like the wallpaper slideshow in Windows. So I got into writing a script. I w...]]></description><link>https://blog.asankasovis.com/wallpaper-slideshows-on-linux</link><guid isPermaLink="true">https://blog.asankasovis.com/wallpaper-slideshows-on-linux</guid><category><![CDATA[Linux]]></category><category><![CDATA[opensource]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sun, 09 Feb 2025 15:38:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739115305610/cdf806b1-cdb3-4744-9350-492a99a5983f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So, I was binge-watching YouTube videos and a random thought came to my mind, like most people: <em>What if I write a bash script to change the wallpaper every minute?</em> I will be like the wallpaper slideshow in Windows. So I got into writing a script. I was quite straightforward. And you can find the final script in my <a target="_blank" href="https://github.com/asankaSovis/Wallpaper_Changer">GitHub Repository</a>.</p>
<p>So first off, how do you change the wallpaper in Linux? Well, it depends on the distro! Since Ubuntu is a common distro and it’s based on Gnome, you can use the Settings app to change the wallpaper. The same goes for most other famous distros.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739113507110/d416f7c6-cddd-48ca-ba8a-efbcf6790ba2.png" alt="Gnome Settings app in Ubuntu 24.10" class="image--center mx-auto" /></p>
<p>But this lacks the option to time the changing of the wallpaper, which is kind of boring. Now I’ve got to admit, there might be better options for wallpaper slideshows in Linux. Having a script is not at all optimized let alone elegant. But I like the simplicity of the idea.</p>
<p>Now if we want to automate the wallpaper creation, we must first have a command that can change the wallpaper. In fact, we do!</p>
<pre><code class="lang-bash">gsettings <span class="hljs-built_in">set</span> org.gnome.desktop.background picture-uri-dark /path/to/wallpaper.jpg
</code></pre>
<p>Now this is for the dark theme, for the light theme, it’s the same but as below.</p>
<pre><code class="lang-bash">gsettings <span class="hljs-built_in">set</span> org.gnome.desktop.background picture-uri /path/to/wallpaper.jpg
</code></pre>
<p>Now it’s a matter of adding the sleep and an indefinite loop.</p>
<p>We want to be able to run this script automatically on startup. Clone the components from the <a target="_blank" href="https://github.com/asankaSovis/Wallpaper_Changer">GitHub repo</a>. If you do not know how to clone the repo, you can also download a release from <a target="_blank" href="https://github.com/asankaSovis/Wallpaper_Changer/releases">Releases</a>. It is recommended to download the latest version.</p>
<p>Create a directory in <code>~/Pictures/</code> called <code>Wallpapers</code>. Copy the required wallpapers to this directory.</p>
<p>Copy the <code>change_wallpaper.sh</code> to a convenient location, possibly to your <em>home (</em><code>~</code>) directory. Open a terminal from the copied location. Enter the following command to make the script run automatically on startup.</p>
<pre><code class="lang-bash">SCRIPT_PATH=<span class="hljs-string">"<span class="hljs-variable">$PWD</span>/change_wallpaper.sh"</span>; SERVICE_NAME=<span class="hljs-string">"change_wallpaper.service"</span>; chmod +x <span class="hljs-variable">$SCRIPT_PATH</span>; <span class="hljs-built_in">echo</span> <span class="hljs-string">"[Unit]
Description=My Script
After=network.target

[Service]
ExecStart=<span class="hljs-variable">$SCRIPT_PATH</span>

[Install]
WantedBy=default.target
"</span> | tee ~/.config/systemd/user/<span class="hljs-string">"<span class="hljs-variable">$SERVICE_NAME</span>"</span>; systemctl --user daemon-reload; systemctl --user <span class="hljs-built_in">enable</span> <span class="hljs-string">"<span class="hljs-variable">$SERVICE_NAME</span>"</span>; systemctl --user start <span class="hljs-string">"<span class="hljs-variable">$SERVICE_NAME</span>"</span>
</code></pre>
<p>You have to make sure <strong>not</strong> to run this command with <code>sudo</code> privileges. That should give you a wallpaper slideshow!</p>
<p>Now it would be boring to have a script that doesn’t have any customization options, so I included additional features to the script as well. Adding additional wallpapers is as simple as copying them to the <code>Wallpapers</code> directory. Both JPEG and PNG wallpapers are supported.</p>
<p>You can also customize the script to your liking. Simply open the script in a text editor and change the following variables:</p>
<ol>
<li><p><code>wallpaper_path="/home/$USER/Pictures/Wallpapers"</code> - Wallpaper path: The wallpapers must be in a directory. Enter the directory path here between double quotes. Do <strong>not</strong> enter the path to a file. Make sure to provide an absolute path relative to the root.</p>
</li>
<li><p><code>update_wallpaper_every=10m</code> - Time to update the wallpaper: Replace <code>10m</code> with your own value. This can be given as: s or (no suffix): seconds (default), m: minutes, h: hours, d: days. Decimals and combinations are also accepted. For example: <code>update_wallpaper_every=5</code> : 5 seconds, <code>update_wallpaper_every=5s</code> : 5 seconds, <code>update_wallpaper_every=2m</code> : 2 minutes, <code>update_wallpaper_every=1.5h</code> : 1.5 hours, <code>update_wallpaper_every=7d</code> : 7 days, <code>update_wallpaper_every=1h30m</code> : 1 hour and 30 minutes. It is recommended to provide a time greater than 5 seconds. The script is also not set to persist time every reboot. Therefore might not change the wallpapers properly for higher timeframes.</p>
</li>
<li><p><code>update_list_every=5</code> - Number of times to wait to update the list of images: This will wait until the given number of times of wallpaper updates to update the list of images in the wallpaper path. For example if <code>update_wallpaper_every=10m</code> and <code>update_list_every=5</code>, the list of wallpapers will be updated every 50 minutes.</p>
</li>
</ol>
<p>Further modifications can be done to the script itself if needed.</p>
<p>Now there are cases where you might want to temporarily stop the script or permanently get rid of it. So:</p>
<ol>
<li><p>In case you want to pause the changing of wallpapers, you can create a file called <code>.override</code> inside the same <code>Wallpapers</code> directory which will pause the slideshow indefinitely until the file is deleted again.</p>
</li>
<li><p>You can check the status of the script by using the following command.</p>
</li>
</ol>
<pre><code class="lang-bash">systemctl --user status <span class="hljs-string">"change_wallpaper.service"</span>
</code></pre>
<blockquote>
<p>NOTE: <strong>Do not</strong> run this command with <code>sudo</code>.</p>
</blockquote>
<ol start="3">
<li>The script can be temporarily stopped by killing the script.</li>
</ol>
<pre><code class="lang-bash">sudo <span class="hljs-built_in">kill</span> -9 $(ps -eo pid,<span class="hljs-built_in">command</span> | grep /bin/bash | grep live_wallpaper_script.sh | tr -d <span class="hljs-string">" "</span> | tr <span class="hljs-string">"/"</span> <span class="hljs-string">"\n"</span> | head -n 1)
</code></pre>
<blockquote>
<p>NOTE: <strong>Have to</strong> run this command with <code>sudo</code>.</p>
</blockquote>
<ol start="4">
<li>The script can be permanently stopped and removed by deleting the service file.</li>
</ol>
<pre><code class="lang-bash">SERVICE_NAME=<span class="hljs-string">"change_wallpaper.service"</span>; systemctl --user stop <span class="hljs-variable">$SERVICE_NAME</span>; systemctl --user <span class="hljs-built_in">disable</span> <span class="hljs-variable">$SERVICE_NAME</span>; rm ~/.config/systemd/user/<span class="hljs-string">"<span class="hljs-variable">$SERVICE_NAME</span>"</span>
</code></pre>
<blockquote>
<p>NOTE: <strong>Do not</strong> run this command with <code>sudo</code>.</p>
</blockquote>
<ol start="5">
<li>In case the script is modified, the service can be restarted to pull updates to the script.</li>
</ol>
<pre><code class="lang-bash">systemctl --user restart <span class="hljs-string">"change_wallpaper.service"</span>
</code></pre>
<blockquote>
<p>NOTE: <strong>Do not</strong> run this command with <code>sudo</code>.</p>
</blockquote>
<p>To report bugs and request features, go to <a target="_blank" href="https://github.com/asankaSovis/Wallpaper_Changer/issues">GitHub issues</a> and create a new Issue. Make sure to include the terminal output and a clear explanation of what you were trying to do and what happened. Also, include device information such as the distro and install path. It will take some time to provide support.</p>
<p>Anyone can contribute to this project. If you're a bash programmer, any new features or bug fixes are greatly appreciated. Any suggestions are also appreciated along with documentation improvements. The same goes for any bug reporting and feature suggestions. Also, if you're willing to, consider trying all features of this script in your distro and providing any feedback; especially if you're on a different distro.</p>
<p>I ran the script on Ubuntu 24.10.</p>
]]></content:encoded></item><item><title><![CDATA[Screensavers on Linux - A Nostalgic Revival]]></title><description><![CDATA[A Bit of Context
Whether Linux or Windows, most of us are nostalgic for screensavers. They were not just there to provide any technical requirements but were also a form of art that we loved to enjoy. With time, the requirement for screensavers has f...]]></description><link>https://blog.asankasovis.com/screensavers-on-linux-a-nostalgic-revival</link><guid isPermaLink="true">https://blog.asankasovis.com/screensavers-on-linux-a-nostalgic-revival</guid><category><![CDATA[Screensavers]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sun, 25 Feb 2024 08:32:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1708849813849/223231ce-3632-47cc-93a3-776dfa074a58.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-a-bit-of-context">A Bit of Context</h1>
<p>Whether Linux or Windows, most of us are nostalgic for screensavers. They were not just there to provide any technical requirements but were also a form of art that we loved to enjoy. With time, the requirement for screensavers has faded away; of course, it's simply better to just blank the screen out anyway. But some of us still love the prospect of the screen turning into a lovely display of electronic art whenever we leave the computer for some time. If you're someone like me, then this tutorial will explain to you how to re-enable screensavers on Linux.</p>
<p>Before we proceed, I'd like to point out that in modern systems, it's probably useless to use a screensaver anyway. Most, if not all displays nowadays will turn themselves off when no signal is present. It's probably better for its durability anyway. On the other hand, it's much safer to just turn off the screen from a cybersecurity perspective. Therefore, please proceed with your caution and responsibility with this tutorial as we're dealing with old technology and we can't guarantee security or reliability. If you're unsure, leave your system as is. But for those of you who are willing to take the risk, let's proceed.</p>
<h1 id="heading-the-xscreensaver">The XScreenSaver</h1>
<p>Since its heydays, Linux has used XScreenSaver to provide the system with screensaver support. However, in 2011, gnome-screensaver version 3 dropped support for screensavers completely, supporting only simple screen blanking. Since then, we simply see the screen blanking itself after the allocated timeout.</p>
<p>However, development for XScreenSaver is still underway and can be easily done on Linux with just a few steps.</p>
<h2 id="heading-installing-the-xscreensaver">Installing the XScreenSaver</h2>
<p>The first step is to install the XScreenSaver on your OS. I am using Ubuntu 23.10 and other Linux distros might have similar steps to what I'm following. In some Ubuntu distros, a program called <code>gnome-screensaver</code> might be present to handle screen blanking. It is important to remove this as it might interfere with the XScreenSaver. To do this, use the following command. In most modern distros, this simply will not even exist; but still, it's better to make sure.</p>
<pre><code class="lang-bash">sudo apt-get remove gnome-screensaver
</code></pre>
<p>The next step is to install the XScreenSaver along with its dependencies.</p>
<pre><code class="lang-bash">sudo apt-get install xscreensaver xscreensaver-data-extra xscreensaver-gl-extra
</code></pre>
<p>This is it! Now the OS will have screensaver support. However, some configurations might need to be done before we call it a day.</p>
<h2 id="heading-changing-a-few-settings">Changing a Few Settings</h2>
<p>If your computer is set to blank after a certain time even when the screensaver is present, is not a good idea. So we will delay the screen blanking time. Go to <strong>Settings &gt; Power</strong> and set the <strong>Screen Blank</strong> to <strong>15 minutes</strong>. This will ensure that the screensaver has plenty of time before the system kicks in and turns off the screen. You can also set it to <strong>Never</strong> but I do not recommend it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708844916826/541e399a-1e19-45e2-ad88-147d8234f25f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-configuring-the-xscreensaver">Configuring the XScreenSaver</h2>
<p>Out-of-the-box, XScreenSaver is set to start the screensaver after 10 minutes. It will choose a random screensaver and display it on the screen. We'd like to choose the screensaver we like to set as the screensaver. Doing this is easy! If you now check your app drawer, you will see a new app titled <strong>Screensaver.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708845207381/ed6225ee-460a-484a-8be1-5b448dde7b44.png" alt class="image--center mx-auto" /></p>
<p>Open this and you will see the XScreenSaver configuration page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708845255021/b4ec9bfd-b50c-488d-812e-75a6b2bf2d0a.png" alt class="image--center mx-auto" /></p>
<p>Sometimes, you might get a Warning such as the one given below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708845274178/69465130-6920-45b3-a514-25ab9ab5e264.png" alt class="image--center mx-auto" /></p>
<p>Hit <strong>OK</strong> and you will see a prompt like below:</p>
<p><img src="https://i.stack.imgur.com/ViUpu.png" alt="Awful font" class="image--center mx-auto" /></p>
<p>This indicates that the screensaver daemon started.</p>
<p>On the <strong>Screensaver Preferences</strong> page, we can change the preferences for our screensavers. Under <strong>Blank After</strong>, set the number of minutes after which to turn on the screensaver. Also, make sure to uncheck the <strong>Fade to Black when Blanking</strong> and <strong>Fade from Black When Unblanking</strong> options under <strong>Advanced &gt; Blanking</strong> tab. Also, set the <strong>Fade Duration</strong> to 1 second or it takes too much time to show the screensaver.</p>
<p>The most important option, however, is the <strong>Mode:</strong> in the <strong>Display Modes</strong> tab. Change it to <strong>Only One Screen Saver</strong> to enable the screensaver selection. Now in the list below, you can choose your favourite screensaver as the default. Go through them and choose the ones that you prefer.</p>
<p>For me, the <strong>Preview</strong> button does not seem to do anything, however, if you prefer to preview the screensaver, simply click <strong>File &gt; Blank Screen Now</strong> and the screensaver will be displayed on the display.</p>
<p>Optionally, you can change settings on certain screensavers by clicking on <strong>Settings...</strong>. Note that some screensavers might not have the option to change their settings.</p>
<h2 id="heading-starting-the-xscreensaver-daemon-at-startup">Starting the XScreenSaver Daemon at Startup</h2>
<p>If you restart your computer, you'll notice that even after the timeout, the screensaver might not start. The reason is that every time the computer restarts, the XScreenSaver daemon does not run automatically. We will do this by adding a startup entry.</p>
<p>To do this, open the <strong>Startup Applications</strong> from the app drawer and click on <strong>Add</strong> to create a new entry.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708847197955/30b5ff00-106e-4556-9e3f-4bbf0b63da6a.png" alt class="image--center mx-auto" /></p>
<p>Under <strong>Name:</strong> give <code>XScreensaver</code>. Under <strong>Command:</strong> give <code>xscreensaver -no-splash</code> and under <strong>Comment:</strong> give <code>Start screensaver daemon</code>.Press <strong>Add</strong> and then <strong>Close</strong> to close the application.</p>
<p>Now, every time you restart the device, the XScreenSaver daemon will run automatically.</p>
<h2 id="heading-fix-a-little-inconvenience">Fix a Little Inconvenience</h2>
<p>If you use the screensaver for some time, you will notice that even when you watch a movie or a YouTube video, the screensaver starts. This can end up being annoying. Unfortunately, there's no proper way to prevent this. But, there's a small hack that we can do to make sure this doesn't happen in most cases.</p>
<p>The trick is to create a bash script that checks if an application is running full screen and disable the daemon if it sees one. This is only a partial fix as whenever you're playing a video without going full-screen, the screensaver will turn on regardless. We will have to deal with it, unfortunately. However, in most cases, we will be doing something on our computer while something is playing without the full-screen mode and it should be fine.</p>
<p>All kudos should go to <a target="_blank" href="https://askubuntu.com/users/231142/terrance">Terrance</a> on <a target="_blank" href="https://askubuntu.com">askubuntu.com</a> for coming up with this ideal solution. The workaround below is from the answer he gave to a question titled <a target="_blank" href="https://askubuntu.com/questions/778688/when-i-watch-a-video-online-the-screen-turns-off-after-a-few-minutes/778817#778817">When I watch a video online the screen turns off after a few minutes</a>, with a few modifications on the terminal.</p>
<p>First, we will install <code>xdotool</code>.</p>
<pre><code class="lang-bash">sudo apt install xdotool
</code></pre>
<p>Then, we will create a folder to save our script.</p>
<pre><code class="lang-bash">mkdir -p ~/.scripts
</code></pre>
<p>In this folder, we will create a bash script file.</p>
<pre><code class="lang-bash">nano ~/.scripts/check_full.bsh
</code></pre>
<p>This will open a nano terminal to type the bash script. In it, paste the following script:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment">#Get DPMS settings</span>
dpms_set=$(xset -q | awk <span class="hljs-string">'/DPMS is/ {print $NF}'</span>)

<span class="hljs-comment">#Get screensaver type and command</span>
scrnsvr=<span class="hljs-string">'/usr/bin/xscreensaver'</span>
scrnsvrcmd=<span class="hljs-string">'/usr/bin/xscreensaver -no-splash'</span>

<span class="hljs-comment">#Sleep Timer in seconds.</span>
SL=300

<span class="hljs-keyword">while</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">do</span>
result=()
<span class="hljs-comment">#Get all window geometries</span>
all=($(xdotool search --name - | <span class="hljs-keyword">while</span> <span class="hljs-built_in">read</span> win; <span class="hljs-keyword">do</span> xdotool getwindowgeometry <span class="hljs-variable">$win</span> | awk <span class="hljs-string">'/Geometry/ {print $2}'</span>; <span class="hljs-keyword">done</span>))

<span class="hljs-comment">#Get all screen resolutions detected and build array.</span>
SCREENS=($(xrandr | awk <span class="hljs-string">'/\*/ {print $1}'</span>))

SCRN=<span class="hljs-string">" <span class="hljs-variable">${SCREENS[*]}</span> "</span>

<span class="hljs-comment">#Get result of all windows and match</span>

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> <span class="hljs-variable">${all[@]}</span>; <span class="hljs-keyword">do</span> <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$SCRN</span> =~ <span class="hljs-string">" <span class="hljs-variable">$item</span> "</span> ]] ; <span class="hljs-keyword">then</span> result+=(<span class="hljs-variable">$item</span>); <span class="hljs-keyword">fi</span>; <span class="hljs-keyword">done</span>

<span class="hljs-comment">#If a result exists disable power management and screensaver</span>
<span class="hljs-keyword">if</span> [[ <span class="hljs-variable">${result[@]}</span> ]]; <span class="hljs-keyword">then</span>
    ps -ef | grep <span class="hljs-variable">$scrnsvr</span> | grep -v grep &gt;/dev/null
    <span class="hljs-keyword">if</span> [[ $? == 0 ]]; <span class="hljs-keyword">then</span> 
    <span class="hljs-built_in">kill</span> $(ps -ef | grep <span class="hljs-variable">$scrnsvr</span> | grep -v grep | awk <span class="hljs-string">'{print $2}'</span>)
    <span class="hljs-keyword">fi</span>
    <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$dpms_set</span> == <span class="hljs-string">"Enabled"</span> ]];<span class="hljs-keyword">then</span>
    xset -dpms
    <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">else</span>    
    ps -ef | grep <span class="hljs-variable">$scrnsvr</span> | grep -v grep &gt;/dev/null
    <span class="hljs-keyword">if</span> [[ $? == 1 ]]; <span class="hljs-keyword">then</span>
    <span class="hljs-variable">${scrnsvrcmd}</span> &amp;
    <span class="hljs-keyword">fi</span>
    <span class="hljs-keyword">if</span> [[ <span class="hljs-variable">$dpms_set</span> != <span class="hljs-string">"Disabled"</span> ]];<span class="hljs-keyword">then</span>
        xset dpms
        <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">fi</span>
result=()
sleep <span class="hljs-variable">$SL</span>
<span class="hljs-keyword">done</span>
</code></pre>
<p>You might need to change the <code>SL=300</code> value depending on what the screensaver start time is set to. I have set it as 10 minutes; which is 600 seconds. So I chose this value to be 300 as it's half the screensaver start time. This allows the script to correctly detect the presence of a full-screen app without compromising performance.</p>
<p>Save this by pressing the key sequence <strong>Ctrl + X &gt; Y &gt; Enter</strong>.</p>
<p>Try running the script by entering the following command:</p>
<pre><code class="lang-bash">~/.scripts/check_full.bsh
</code></pre>
<p>If you get an error that looks like below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708848738447/33ae05c0-a0bc-4d94-98a7-77f22f9296f1.png" alt class="image--center mx-auto" /></p>
<p>Enter the command:</p>
<pre><code class="lang-bash">chmod +x ~/.scripts/check_full.bsh
</code></pre>
<p>This will mark the script as executable. Now run the script again from the previous command and it should show like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708848838215/61eb1f5b-25c5-4b52-9364-192881e20ec5.png" alt class="image--center mx-auto" /></p>
<p>This indicates that the script is running and working. If it throws any errors, you will need to double-check the script.</p>
<p>You can press <strong>Ctrl + C</strong> and close the terminal.</p>
<p>Next, we will set this script to also start automatically every time we turn on the computer. As before, open the <strong>Startup Applications</strong> from the app drawer and click on <strong>Add</strong> to create a new entry. Under <strong>Name:</strong> give <code>Check_Full</code>. Under <strong>Command:</strong> give <code>bash -c 'sleep 5 &amp;&amp; /home/asanka/.scripts/check_full.bsh'</code> and under <strong>Comment:</strong> give <code>Prevent screensaver from activating when full screen video is playing</code>. Press <strong>Add</strong> and then <strong>Close</strong> to close the application.</p>
<p>Now, every time you restart the device, the script to check for full-screen applications will run automatically.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Screensavers, once a well-known feature of retro computers, have seen their role fade away in the modern days. While their original purpose of preventing screen burn-in on CRT monitors is no longer relevant with today's displays, screensavers still have some benefits and will always hold a nostalgic charm for many of us enthusiasts.</p>
<h1 id="heading-resources">Resources</h1>
<ul>
<li><p><a target="_blank" href="https://askubuntu.com/questions/778688/when-i-watch-a-video-online-the-screen-turns-off-after-a-few-minutes/778817#778817">'When I watch a video online the screen turns off after a few minutes' post on askubuntu.com</a></p>
</li>
<li><p><a target="_blank" href="https://www.unixmen.com/installing-xscreensaver-ubuntu/">Installing XScreenSaver In Ubuntu article on Unixmen</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/XScreenSaver">Article about XScreenSaver on wikipedia.org</a></p>
</li>
<li><p><a target="_blank" href="https://www.jwz.org/xscreensaver/">Official XScreenSaver homepage</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Screensaver">Article about screensavers on wikipedia.org</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Fixing the Issue with Some AppImages not Running on Modern Linux]]></title><description><![CDATA[A Bit of Context
Nowadays, Linux has several packaging methods that allow cross-compatibility among different Linux distros. All of them come with their ups and downs and choosing the one that chooses you is important. But sometimes, we don't have an...]]></description><link>https://blog.asankasovis.com/fixing-the-issue-with-some-appimages-not-running-on-modern-linux</link><guid isPermaLink="true">https://blog.asankasovis.com/fixing-the-issue-with-some-appimages-not-running-on-modern-linux</guid><category><![CDATA[Ubuntu]]></category><category><![CDATA[Linux]]></category><category><![CDATA[appimage]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sun, 21 Jan 2024 15:22:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705850457568/00e42df8-e34c-42fd-b329-eabd925e9056.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-a-bit-of-context">A Bit of Context</h1>
<p>Nowadays, Linux has several packaging methods that allow cross-compatibility among different Linux distros. All of them come with their ups and downs and choosing the one that chooses you is important. But sometimes, we don't have any other option but to use an application that comes in a specific packaging format.</p>
<h1 id="heading-appimages-a-powerful-packaging-format-but-with-a-flaw">AppImages - A Powerful Packaging Format... But with a Flaw</h1>
<p>AppImages are one such format for distributing software on Linux that doesn't require installation. They're essentially self-contained applications that run on most Linux distributions without needing superuser privileges. This makes them a great option for users who want to try out new software without having to worry about messing up their system, or for developers who want to distribute their software more easily.</p>
<p>AppImages are a powerful packaging format but a major issue exists with its use of the <code>libfuse2</code> library. <code>libfuse2</code> is a library that allows user-space programs to interact with the Linux kernel's filesystem. Some AppImages rely on it for features like virtual filesystems or encrypted storage. However, starting with Ubuntu 22.04 and other distributions <code>libfuse2</code> is no longer included by default. This is due to security concerns and technical limitations of the older library version.</p>
<p>Developers are encouraged to upgrade to the latest libfuse3 but some programs have still not upgraded their programs to the <code>libfuse3</code> library. This makes these AppImages unusable in modern Linux versions.</p>
<h1 id="heading-the-problem">The Problem</h1>
<p>If you try to double-click these AppImages, you might notice that they do not result in anything. In this article, I will use the <a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop"><strong>nRF Connect for Desktop</strong></a> as an example since as of writing this article, it still doesn't work for modern distributions such as mine: Ubuntu 23.10. We can see the actual problem by running it in the terminal.</p>
<p>To do this, navigate to the folder with the downloaded AppImage from Nautilus and right-click on it to select <em>Open in Terminal</em>. On the terminal, typing the name of the package and pressing enter will attempt to run the program from the terminal which will throw the following error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703482256835/4cc9c1fd-5fbf-4816-8190-c426ad1b4369.png" alt="libfuse2 Error" class="image--center mx-auto" /></p>
<h1 id="heading-the-solution">The Solution</h1>
<p>The solution provided in this message is to install <code>libfuse2</code> using the following command.</p>
<pre><code class="lang-bash">sudo add-apt-repository universe
sudo apt install libfuse2
</code></pre>
<p>However, if you're on an Ubuntu version on or above 22.04 <strong><mark>DO NOT ATTEMPT TO DO THIS</mark></strong> as it <strong><mark>WILL BREAK YOUR SYSTEM</mark></strong>. If done, you will have to reinstall the whole desktop environment as well as all the installed applications. At this point, reinstalling the system is the best option.</p>
<p>But there is a simple and elegant workaround for this issue. This is to unpack the AppImage and run it by executing the script. This has the added advantage of bypassing the need for the operating system to mount a separate filesystem to extract and run the AppImage every time it's executed.</p>
<p>The way you can do this is to enter the following command after opening the terminal in the folder with the AppImage.</p>
<pre><code class="lang-bash">chmod +x ./nrfconnect-4.3.0-x86_64.appimage
./nrfconnect-4.3.0-x86_64.appimage --appimage-extract
</code></pre>
<p>I'd recommend creating a new folder in your home directory like '<em>AppImages'</em> and copying the AppImage there before extracting the AppImage in this folder using the above command. Now within this extracted folder, you will find the contents of the app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703427102357/3c426b06-3935-4586-853d-32bb730e7a6b.png" alt="Extracted folder of the AppImage" class="image--center mx-auto" /></p>
<p>Now first open another terminal in this folder and enter the following command to execute the program.</p>
<pre><code class="lang-bash">./AppRun
</code></pre>
<p>If this results in the file opening in a text editor, enter the following command first to change the file to executable.</p>
<pre><code class="lang-bash">sudo chown +x ./AppRun
</code></pre>
<p>You will see that the app runs without an issue.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703427497022/968badec-234d-49af-913f-5fda86850c41.png" alt="App Running after the Extraction" class="image--center mx-auto" /></p>
<h1 id="heading-make-an-elegant-way-to-launch-the-application">Make an Elegant way to Launch the Application</h1>
<p>We can also make the application appear in the App Launcher menu as an entry. To do this, we will rename the folder in which the <em>AppRun</em> file exists to something convenient. In this case, I have already renamed it to <em>nRF</em>.</p>
<p>Now navigate to User Home &gt; <em>.local</em> &gt; <em>share</em> &gt; <em>applications</em>. If <em>.local</em> is not visible, press CTRL + H to reveal hidden files and folders. In this, open a terminal window and use the following command to create a new desktop entry.</p>
<pre><code class="lang-bash">sudo nano <span class="hljs-string">'nRF Connect.desktop'</span>
</code></pre>
<p>You can use any name for the application name. Make sure to use only letters and numbers along with spaces to reduce conflicts and end the name with <em>.desktop</em> as given. This will open the nano text editor. In it, paste the following. Make sure that the paths in <code>Exec</code> and <code>Icon</code> point to the correct locations.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/usr/bin/env xdg-open</span>
[Desktop Entry]
Version=1.0
Type=Application
Terminal=<span class="hljs-literal">false</span>
Exec=/home/asanka/AppImages/nRF/AppRun
Name=nRF Connect Desktop
Comment=nRF Connect Desktop
Icon=/home/asanka/AppImages/nRF/nrfconnect.png
</code></pre>
<p>Here, you can include the path to the AppRun file of your specific application under <code>Exec</code>. The <code>Name</code> and <code>Comment</code> should be the app name that should appear in the launcher. The Icon should point to a PNG of the application. The AppImages usually come with an icon, however, if you do not have one, simply download the logo of the application as a PNG image and copy it into that application directory.</p>
<p>Now save the file by pressing CTRL + X &gt; <em>Y</em> &gt; Enter. Then if you check your launcher, you will see the application icon. Clicking on it will run the program.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703429291241/0165acba-7692-4cc3-970f-55ae039bae21.png" alt="nRF Connect Desktop on the App Launcher" class="image--center mx-auto" /></p>
<h1 id="heading-reference">Reference</h1>
<ul>
<li><p><a target="_blank" href="https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop/Download#infotabs">nRF Connect Desktop Download</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/AppImage/AppImageKit/wiki/FUSE">AppImage FUSE Requirement Details</a></p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Filesystem_in_Userspace">Wikipedia Article on FUSE</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/libfuse/libfuse">libfuse GitHub Repository</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/OpenShot/openshot-qt/issues/4789">Ubuntu 22.04: Appimage doesn't start : libfuse.so.2: cannot open shared object file: No such file or directory - Issue on openshot-qt Github Repository</a></p>
</li>
<li><p><a target="_blank" href="https://linuxconfig.org/how-to-create-desktop-shortcut-launcher-on-ubuntu-22-04-jammy-jellyfish-linux">How to create desktop shortcut launcher on Ubuntu 22.04 Jammy Jellyfish Linux - LinuxConfig.org</a></p>
</li>
<li><p><a target="_blank" href="https://appimage.org/">Official AppImages Site</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Setting Up the Sinhala Keyboard on Ubuntu/Linux]]></title><description><![CDATA[As the native language of Sri Lanka, Sinhala typesetting is crucial to any Sri Lankan. However, Sinhala language support had been minimal in most operating systems until recently. However, Sinhala support in Windows has improved considerably with Win...]]></description><link>https://blog.asankasovis.com/setting-up-the-sinhala-keyboard-on-ubuntulinux</link><guid isPermaLink="true">https://blog.asankasovis.com/setting-up-the-sinhala-keyboard-on-ubuntulinux</guid><category><![CDATA[Ubuntu]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sat, 20 Jan 2024 13:39:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705757848880/0aeac1aa-62d0-465e-a7c6-c84ae1750fd2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As the native language of Sri Lanka, Sinhala typesetting is crucial to any Sri Lankan. However, Sinhala language support had been minimal in most operating systems until recently. However, Sinhala support in Windows has improved considerably with Windows 10. However when it comes to Linux, even though the support is appreciatable, the typesetting in Sinhala is still a bit clunky. But even though the out-of-the-box experience for Sinhala is imperfect, we can still use external methods to easily set Sinhala language support perfectly. In this short article, we will discuss how.</p>
<h1 id="heading-installing-the-helakuru-sinhala-package">Installing the Helakuru Sinhala Package</h1>
<p>From my experience, the Helakuru package contains the best Sinhala support at the moment, and it's also straightforward to set up. Simply visit the <a target="_blank" href="https://www.helakuru.lk/download/?fid=bGludXhfcA==&amp;key=1703386486-key65879d764b5c82.92017782">link given</a> here to download the Debian package. For other Linux packaging types, visit <a target="_blank" href="https://www.helakuru.lk/">this link</a> and choose your preferred distribution.</p>
<p>Extract the downloaded zip file and within this, you will find the Debian installer as '<em>helakuru.deb</em>' or like.</p>
<p>Now you can double-click this Debian package to open the software centre. If it doesn't open the package in the software centre, right-click and choose '<em>Open With...</em>' Now choose '<em>Software Install</em>' and click <em>Open</em>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703392966084/12e43aad-225a-4a00-9e0d-d6eaa290b8c3.png" alt="Open File Dialog Box - Ubuntu 23.10" class="image--center mx-auto" /></p>
<p>Click on Install and it will deploy Sinhala keyboard support on Linux.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703393457203/1aed3d98-b04f-4077-b496-4cc079c6b782.png" alt="Software Install after the Helakuru Debian file is installed" class="image--center mx-auto" /></p>
<p>Now log out of the device and log back in to activate the changes on the device. Now if you go into <em>Settings</em> &gt; <em>Keyboard</em> &gt; <em>Input Sources</em> &gt; <em>Add an Input Source</em> (+ Sign), you will see <em>Sinhala</em> as an input method.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703393695575/d98db402-d25a-4b99-a97e-bb9fc19b5850.png" alt="Sinhala as an option in Keyboard" class="image--center mx-auto" /></p>
<p>If you click on <em>Sinhala</em>, you will find multiple entries of Sinhala language installed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703393879861/b92375ab-0dad-41c7-a3e0-36402e53e4d6.png" alt="Sinhala entries in Input Sources" class="image--center mx-auto" /></p>
<p>The most familiar options out of these would be Wijesekara (<em>Sinhala (si-helakuru-wijesekara (m17n)</em>) and Phonetic (<em>Sinhala (si-helakuru-phonetic (m17n)</em>). Clicking on either of these and clicking on <em>Add</em> will add these as an input language. Now if you click on the small language icon that appears on the command panel, you will find the selected language preferences appear.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703393949339/dcdb060b-ac17-4049-8db8-289b0f5580ae.png" alt="Language Selection on Command Panel" class="image--center mx-auto" /></p>
<p>You can add, remove or change these keyboard layouts by clicking on <em>Keyboard Settings</em> in the above menu. Unfortunately, clicking on Show <em>Keyboard Layout</em> will only display the English (US) keyboard layout. However, in case you need to manually select characters from a menu, you can use the <em>Character Map</em> application. This is generally installed by default on major Linux distributions. If not, you can find it in your respective Application Store.</p>
<p>Launching this application and selecting Sinhala under Scripts, will allow you to select and copy any Sinhala character to your clipboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703394565011/04bf72e2-9351-41f0-bddb-f617daf551c3.png" alt="Character Map" class="image--center mx-auto" /></p>
<p>With this, you can type in Sinhala.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703394681525/40708d01-c668-4b61-a8bf-1965da7fcef9.png" alt="Typing in Sinhala" class="image--center mx-auto" /></p>
<h1 id="heading-lk-slug-sinhala-language-pack">LK-SLUG Sinhala Language Pack</h1>
<p>However, there exists another method to set up Sinhala language support used in the past. This is the LK-SLUG language pack. This comes with fonts as well as the keyboard layout. However in my experience, for modern Ubuntu systems, this method is not that applicable. The layout is a bit different from the modern Sinhala layouts we find today such as Singlish, Phonetic and Wijesekara. But if required, this option is also available.</p>
<p>To install the LK-SLUG Sinhala language pack, enter the following command in the terminal.</p>
<pre><code class="lang-bash">sudo apt-get install fonts-lklug-sinhala ibus im-switch ibus-m17n m17n-db m17n-contrib language-pack-si-base
</code></pre>
<p>Enter your password if prompted and press enter. Once installed, you can log out; log back in and go to settings as we discussed before. If all goes well, you will see similar layouts under <em>Add an Input Source</em> including a few more options.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1703422697313/091cdf81-fa69-4b09-acf7-be6c2b2e8808.png" alt="Add an Input Source Menu" class="image--center mx-auto" /></p>
<p>This will conclude the Sinhala language setup in modern Ubuntu systems. සිංහල භාෂාව සමඟ ඉදිරියට ලේඛන කරන ඔබට සුභ දවසක්.</p>
<h1 id="heading-references">References</h1>
<ul>
<li><p><a target="_blank" href="https://askubuntu.com/questions/105544/install-sinhala-unicode-pack">install sinhala unicode pack - AskUbuntu</a></p>
</li>
<li><p><a target="_blank" href="https://askubuntu.com/questions/459349/sinhala-unicode-wijesekara-keyboard-in-ibus-on-ubuntu-14-04-not-working">Sinhala unicode (Wijesekara keyboard) in iBus on Ubuntu 14.04 not working - AskUbuntu</a></p>
</li>
<li><p><a target="_blank" href="https://askubuntu.com/questions/1275466/how-to-install-wijesekara-sinhala-keyboard">How to install WIjesekara Sinhala keyboard? - AskUbuntu</a></p>
</li>
<li><p><a target="_blank" href="https://pariganakalipi.blogspot.com/2014/08/InstallingSinhalaFORUbuntu.html">Ubuntu සදහා සිංහල Install කරමු - පරිගණක ලිපි</a></p>
</li>
<li><p><a target="_blank" href="https://groups.google.com/g/Sinhala-Unicode/c/TEozgIPIIaY?pli=1">Sinhala input on Ubuntu 20.04 - Google Groups</a></p>
</li>
<li><p><a target="_blank" href="https://www.helakuru.lk/">Helakuru Download</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[A Bit of Context...]]></title><description><![CDATA[Hello 👋,
I have been a huge proponent of open-source software. Yet, I have always used Windows as my operating system. However, I tried several times to switch to Ubuntu, but they all failed due to a lack of experience and my workflows being too rel...]]></description><link>https://blog.asankasovis.com/a-bit-of-context</link><guid isPermaLink="true">https://blog.asankasovis.com/a-bit-of-context</guid><category><![CDATA[Linux]]></category><category><![CDATA[Windows]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sun, 22 Oct 2023 16:47:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697992664014/9642a12e-3735-40f6-8e9f-6dfd011ab185.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello 👋,</p>
<p>I have been a huge proponent of open-source software. Yet, I have always used Windows as my operating system. However, I tried several times to switch to Ubuntu, but they all failed due to a lack of experience and my workflows being too reliant on Windows. Times have changed and I find it even more important to switch to the Linux ecosystem.</p>
<p>When I first started, I found it hard to find any detailed resources for anyone willing to make the switch. However, with time I have acquired a substantial amount of experience on Linux and the project has improved quite a lot to accommodate new users; not to mention the ever-growing ecosystem of compatible software.</p>
<h1 id="heading-but-why-now">But Why Now?</h1>
<p>There are several reasons why I wanted to take the decision. An important one is the fact that Windows has become more and more cluttered over time. I use Windows 11 and it feels so heavy on my hardware. Even after cleaning the hard disk and making sure not to have any virus or malware, the OS starts to feel laggy. With support for Windows 10 coming to an end soon; and the fact that I hate the aesthetics of Windows 10, I do not like to switch to Windows 10.</p>
<p>Another point to make is the interface design. Windows 11 is much better compared to the Windows 10 interface, however, I still find these inconsistencies not pleasing to the eye. Maybe I simply need a change to a different experience altogether. I have always loved the gnome interface and the new Ubuntu 23.10 design caught my eye. This is also a reason why I am willing to try again.</p>
<p>Windows XP and 7 were great operating systems at the time. But since then, Microsoft continued to disappoint. They've diverted into different business models that are harder and harder for me to keep up. With rumours of a subscription-based OS, it's not going to be affordable for me to continue using Windows. Overall, I don't find the philosophy behind Windows appealing anymore.</p>
<h1 id="heading-a-bit-of-context">A Bit of Context</h1>
<p>I have worked with Linux for quite a while now. Even my work laptop is running Linux and my office workflows have become completely reliant on Ubuntu. Still, my personal laptop had always been Windows. The biggest issue had been the workflows that I've been used to. Some of these require programs running only on Linux. On the other hand, I've been used to the interface since my childhood. Breaking these habits will need time.</p>
<h1 id="heading-the-approach">The Approach</h1>
<p>I have several key workflows that I follow. The first step would be to identify these workflows. This allows me to identify programs that require alternatives on Linux. Next would be to try replacing them on Windows itself. If not possible, I'll have to identify ways to run them on Linux.</p>
<p>Once This step is complete, I'll prepare the laptop by moving all my data out of the Windows partition into another partition and linking those paths to Windows libraries. This allows me to install Ubuntu into a new partition and share the data between both OS. This way, I will not run into document issues.</p>
<p>With both OS available, I'll try to move each workflow into Ubuntu. Once I'm confident that the transition is complete, I'll remove Windows completing the transition.</p>
<h1 id="heading-final-thoughts">Final Thoughts</h1>
<p>This is just an idea that I've been having for quite some time. The reason that I started this series is to document all the steps I follow in this journey. Maybe I might succeed, or maybe I won't, but either way, I have a feeling that some of the research I'll provide will be helpful to someone in the future. I don't have a deadline for this series and I prefer to take as much time as I require. Thus, I'm not sure when the next update will arrive. Until then...</p>
<p>Cheers 🎉</p>
]]></content:encoded></item><item><title><![CDATA[#2 The nRF7002, Zephyr and the Nordic Platform - Prometheus v2.0 Devlog]]></title><description><![CDATA[Hello 👋,
Before getting too carried away with the project, I wanted to do a bit of research on the platform that I'm dealing with. So I did a bit of research on the nRF development kits and the Nordic SoCs. The results I found were interesting and I...]]></description><link>https://blog.asankasovis.com/2-the-nrf7002-zephyr-and-the-nordic-platform-prometheus-v20-devlog</link><guid isPermaLink="true">https://blog.asankasovis.com/2-the-nrf7002-zephyr-and-the-nordic-platform-prometheus-v20-devlog</guid><category><![CDATA[Matter]]></category><category><![CDATA[fire extinguisher]]></category><category><![CDATA[iot]]></category><category><![CDATA[Nordic Semiconductor]]></category><category><![CDATA[hackster.io]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sat, 21 Oct 2023 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699195375667/85c99c67-7cae-46fa-91e7-c67d541c17a3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello 👋,</p>
<p>Before getting too carried away with the project, I wanted to do a bit of research on the platform that I'm dealing with. So I did a bit of research on the nRF development kits and the Nordic SoCs. The results I found were interesting and I wanted to share them.</p>
<p>The first is about nRF. I managed to get the nRF development environment up and running which I consider to be a huge milestone. The process was quite simple and required little to no effort. I simply followed the <a target="_blank" href="https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK/GetStarted">tutorial</a> provided by Nordic themselves.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699193418892/59b3dcc0-0297-423d-8d0e-25a7d76eee7e.png" alt class="image--center mx-auto" /></p>
<p>After this, my next plan was to get the blinky LED sample from Zephyr up and running. This was also not that complicated. I did follow a small <a target="_blank" href="https://youtu.be/rvDdev18PAI?si=WIrH7iT6G-aEPwPf">tutorial</a> which helped to understand what I'm doing, especially since I don't have prior experience with Zephyr. This worked out well and I had the LED blinking.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699194172693/7906e994-4881-453d-9be7-feeab3c41934.png" alt class="image--center mx-auto" /></p>
<p>There are several ways to program the nRF board but I decided to go with the device tree and Zephyr OS method. This is much simpler and platform-independent which is ideal in my scenario.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699194702031/7ae78c8f-9541-41e5-a3f1-cae40723c7d9.gif" alt class="image--center mx-auto" /></p>
<p>In the next article, I plan to discuss a bit about the hardware design.</p>
<p>Until then... Cheers! 🎉</p>
<h1 id="heading-reference">Reference</h1>
<ul>
<li><p><a target="_blank" href="https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK/GetStarted">Getting Started guide for nRF7002 DK</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/rvDdev18PAI?si=WIrH7iT6G-aEPwPf">Zephyr/nRF Blinky Tutorial</a></p>
</li>
<li><p><a target="_blank" href="https://youtube.com/playlist?list=PLoKOKJqgqHs9mReagSVnB8FAQBJuRMCEt&amp;si=-6g6zJYnovS3XYu0">Zephyr and nRF Connect SDK</a></p>
</li>
<li><p><a target="_blank" href="https://youtube.com/playlist?list=PLJKv3qSDEE-nZi9wWubnpYUiUBRTyRPrN&amp;si=_kjNp_sdAmete2XT">Zephyr: Tidbits</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[#1 Let's Start from the Beginning - Prometheus v2.0 Devlog]]></title><description><![CDATA[Hello 👋,
As you might already know, I have a project called Prometheus Fire Alarm System on GitHub. Prometheus is a next-generation fire alarm system Designed to take fire safety to the next level. This fire alarm system is designed to detect, indic...]]></description><link>https://blog.asankasovis.com/1-lets-start-from-the-beginning-prometheus-v20-devlog</link><guid isPermaLink="true">https://blog.asankasovis.com/1-lets-start-from-the-beginning-prometheus-v20-devlog</guid><category><![CDATA[Matter]]></category><category><![CDATA[fire extinguisher]]></category><category><![CDATA[iot]]></category><category><![CDATA[Nordic Semiconductor]]></category><category><![CDATA[hackster.io]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Sat, 14 Oct 2023 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698079803295/f56d4239-2541-45c5-8d9e-03562433c4c2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello 👋,</p>
<p>As you might already know, I have a project called <a target="_blank" href="https://github.com/asankaSovis/prometheus-fire-alarm">Prometheus Fire Alarm System</a> on GitHub. Prometheus is a next-generation fire alarm system Designed to take fire safety to the next level. This fire alarm system is designed to detect, indicate and extinguish fire by using necessary precautions.</p>
<p>Recently, I applied for a proposal for an improved version of Prometheus using the Matter Network and the <a target="_blank" href="https://www.nordicsemi.com/">Nordic Semiconductors</a> <a target="_blank" href="https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK">nRF7002 Development Kit</a>. The competition <a target="_blank" href="https://www.hackster.io/contests/makeitmatter"><em>Make It Matter</em></a>, is held by Nordic Semiconductors on the <a target="_blank" href="https://www.hackster.io/">hackster.io</a> platform. As I got selected among the 100 best proposals, I received an nRF7002 Development Kit to build a prototype of the project.</p>
<h1 id="heading-fire-alarm-system-why">Fire Alarm System... Why?</h1>
<p>Let's start with the obvious! One of the key requirements for a smart home is the safety and well-being of the inhabitants. This is why it's important to have devices to actively monitor and rectify any threats that occur within the house. One such threat is the hazard of fire. According to the WHO, more than 300,000 deaths occur every year due to fire-related hazards <a target="_blank" href="https://scholar.google.com/scholar_lookup?journal=MMWR:+Morbidity+and+Mortality+Weekly+Report&amp;title=Prevention.+Deaths+resulting+from+residential+fires+and+the+prevalence+of+smoke+alarms--United+States,+1991-1995&amp;author=CfD+Control&amp;volume=47&amp;issue=38&amp;publication_year=1998&amp;pages=803-6&amp;pmid=9776167&amp;">[1]</a>.</p>
<p>Thus we see the importance of incorporating a fire monitoring and extinguishing system into the modern smart home. This should actively monitor the environment for critical changes in the levels of humidity, temperature, and carbon dioxide and take necessary precautions to rectify any fires that get detected. The residents should also get the convenience of actively monitoring the state of the alarm and extinguishing system whenever they require it. This is the premise of the Prometheus Fire Alarm System v2.0.</p>
<h1 id="heading-big-brother-prometheus-v10">Big Brother: Prometheus v1.0</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698077335485/29a402d2-b70b-4406-b620-468ed69951bb.jpeg" alt="Prometheus Fire Alarm System v1.0" class="image--center mx-auto" /></p>
<p>This version aimed at developing a cost-effective monitoring and extinguishing system that is robust and scalable. The following were the targets of this project:</p>
<ol>
<li><p><strong>Cost</strong> - Develop a system based on off-the-shelf components that are cost-effective</p>
</li>
<li><p><strong>Scalable</strong> - Availability for multiple monitoring devices to operate and synchronize in real-time</p>
</li>
<li><p><strong>Independent</strong> - Whether connected or not, the device should monitor and react on its own without the involvement of the operator</p>
</li>
</ol>
<p>There are four main sections and components for the proper functioning of the system. It will help to complete all the stages that are mentioned above.</p>
<ol>
<li><p>Fire sensors</p>
</li>
<li><p>Extinguishing valves</p>
</li>
<li><p>Control unit</p>
</li>
<li><p>Software system</p>
</li>
<li><p>Structural design</p>
</li>
</ol>
<p>This project was already completed and has been demonstrated to be effective. This demonstration is available under the following YouTube video.</p>
<p><a target="_blank" href="https://youtu.be/5h3k6kufkHo"><img src="https://user-images.githubusercontent.com/46389631/192273259-fb92e6f6-b95d-4e68-a962-5505359a668c.png" alt="Prometheus Fire Alarm System - Demonstration" /></a></p>
<h1 id="heading-whats-next">What's Next?</h1>
<p>The next step would be to improve the Prometheus Fire Alarm System into a smart home device, bringing in the cost-effective, independent, and scalable fire alarm and extinguishing system to the smart home. This will allow it to sit alongside other sensors and systems to provide all the smart homes with safety from fire.</p>
<p>The improvements thus suggested will be as follows.</p>
<ol>
<li><p>Add a built-in charging system to allow the system to run when even the power is lost</p>
</li>
<li><p>Redesign the system to use the <strong>nRF7002</strong> chip instead of an ATMega</p>
</li>
<li><p>Rewrite the firmware to incorporate the Matter protocol</p>
</li>
</ol>
<h1 id="heading-what-to-expect">What to Expect...</h1>
<p>The reason why I started this devlog is to keep track of the progress of the project. I intend to follow a strict development timeline to make sure the final demonstration is ready in time. The biggest milestones are as follows.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697641107204/1ea1c2b1-23ca-42cf-9665-9f3a8f9784f7.png" alt /></p>
<p>In the next article, I will share some of the research I did on the nRF7002 Development Kit and the Matter Network.</p>
<p>Until then... Cheers! 🎉</p>
<h1 id="heading-some-further-resources">Some Further Resources</h1>
<ul>
<li><p><a target="_blank" href="https://github.com/asankaSovis/prometheus-fire-alarm/tree/main">Prometheus Fire Alarm System Firmware Repo</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/asankaSovis/prometheus-command-panel">Prometheus Command Panel Repo</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/asankaSovis/prometheus-fire-alarm/blob/main/Additional%20Material/Engineering%20Design%20Project%20-%20Project%20Report.pdf">Prometheus Fire Alarm System v1.0 Report</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/5h3k6kufkHo?si=pq6S2FBMBYGGU_1R">Prometheus Fire Alarm System Demo Video (Youtube)</a></p>
</li>
</ul>
<h1 id="heading-references">References</h1>
<ol>
<li><p><a target="_blank" href="https://scholar.google.com/scholar_lookup?journal=MMWR:+Morbidity+and+Mortality+Weekly+Report&amp;title=Prevention.+Deaths+resulting+from+residential+fires+and+the+prevalence+of+smoke+alarms--United+States,+1991-1995&amp;author=CfD+Control&amp;volume=47&amp;issue=38&amp;publication_year=1998&amp;pages=803-6&amp;pmid=9776167&amp;">Deaths resulting from residential fires and the prevalence of smoke alarms--United States, 1991-1995</a></p>
</li>
<li><p><a target="_blank" href="https://www.nordicsemi.com/Products/Development-hardware/nRF7002-DK">nRF7002 DK Reference</a></p>
</li>
<li><p><a target="_blank" href="https://csa-iot.org/all-solutions/matter/">Matter Specification</a></p>
</li>
<li><p><a target="_blank" href="https://www.nordicsemi.com/">Nordic Semiconductor Homepage</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Beowulf Cluster Setup]]></title><description><![CDATA[1. Introduction
A Beowulf cluster is a type of High-Performance Computing (HPC) cluster that is designed to perform parallel computations on large data sets or complex computational problems. It is named after the legendary warrior Beowulf, who is kn...]]></description><link>https://blog.asankasovis.com/beowulf-cluster-setup</link><guid isPermaLink="true">https://blog.asankasovis.com/beowulf-cluster-setup</guid><category><![CDATA[cluster]]></category><category><![CDATA[High Performance Computing ]]></category><category><![CDATA[optimization]]></category><category><![CDATA[beowulf]]></category><category><![CDATA[almanac]]></category><dc:creator><![CDATA[Asanka Akash Sovis]]></dc:creator><pubDate>Tue, 18 Jul 2023 15:40:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689694341218/904c4810-1102-467f-a062-14d5fd5dc4fc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-1-introduction">1. Introduction</h2>
<p>A Beowulf cluster is a type of High-Performance Computing (HPC) cluster that is designed to perform parallel computations on large data sets or complex computational problems. It is named after the legendary warrior Beowulf, who is known for his strength and ability to overcome seemingly insurmountable challenges.</p>
<p>The main feature of a Beowulf cluster is that it is created by using all the open-source resources available. Beowulf clusters are typically built using commodity hardware components: such as standard x86-based processors, Ethernet switches, and network interface cards. The nodes in a Beowulf cluster are connected through a high-speed local area network (LAN), which allows them to communicate and share resources efficiently.</p>
<p>One of the key features of a Beowulf cluster is its ability to distribute computing tasks across multiple nodes in parallel, allowing for faster processing times and improved performance. This is achieved through the use of a Message-Passing Interface (MPI), which allows nodes to communicate and coordinate their efforts in executing complex computations.</p>
<p>Beowulf clusters are commonly used in scientific research, engineering and other fields where large-scale computational tasks are required. They can be used to simulate complex physical processes, analyze massive data sets, and perform other computationally intensive tasks that would be impractical or impossible to perform on a single machine.</p>
<p>Overall, Beowulf clusters represent a powerful and cost-effective solution for high-performance computing, allowing organizations to harness the power of parallel computing to solve complex problems and drive innovation. Implementing a Beowulf cluster involves several steps, including hardware selection, software configuration, and network setup.</p>
<h2 id="heading-2-hardware-selection">2. Hardware Selection</h2>
<p>The hardware components required to follow this tutorial are as follows.</p>
<ul>
<li><p>More than one x86-based computer (these can be low-powered)</p>
</li>
<li><p>A router/switch with enough ethernet ports and cables to connect all the computers and internet access</p>
</li>
<li><p>A monitor, keyboard and optionally a mouse</p>
</li>
<li><p>USB Stick (At least 8GB)</p>
</li>
<li><p>A separate computer for setting up the cluster</p>
</li>
</ul>
<p>To make this tutorial the below components are used. It is not essential to use exactly these items but these are mentioned simply to get an idea of how to choose these components.</p>
<ul>
<li><p>Three 64-bit HP desktop computers with 4GB of RAM, CPUs with four cores at 1.5 GHz and a hard disk of 500GB</p>
</li>
<li><p>ADSL router with four ethernet ports</p>
</li>
<li><p>Dell monitor and Logitech keyboard</p>
</li>
<li><p>8GB USB stick</p>
</li>
</ul>
<h2 id="heading-3-choosing-an-operating-system">3. Choosing an Operating System</h2>
<p>In the very definition of a Beowulf cluster, it is mentioned <strong>open source</strong> software. Thus, it is essential to use an open-source operating system such as Linux to run on these computers. The most common OS used is <a target="_blank" href="https://ubuntu.com/download/server">Ubuntu Server</a> although any of the available Linux OS would be suitable with slight variations of the software used and steps mentioned. In this example <a target="_blank" href="https://releases.ubuntu.com/22.04.2/ubuntu-22.04.2-live-server-amd64.iso">Ubuntu Server 22.04.2</a> is used however, other versions should also work with the above disclaimers.</p>
<h2 id="heading-4-preparing-for-the-setup">4. Preparing for the Setup</h2>
<p>Before starting to implement the cluster, a few things have to be taken care of. These are essential for the correct setting up of the cluster. Make sure to follow these steps carefully before moving further.</p>
<h3 id="heading-1-setting-up-the-hardware">1. Setting up the Hardware</h3>
<p>The first step is to set up the hardware correctly. This includes connecting the computers to the router via the ethernet cables. Pick one computer to be the master and the rest of the computers to be the slaves. The master computer or <em>master node</em> as referred to in Beowulf terms, is the computer that runs the program itself. This node breaks the process into multiple blocks and sends it to the slave computers or <em>nodes</em> to be processed. The router should be connected to the internet by suitable means. Internet connection is not essential for the operation of the Beowulf cluster but is only important for setting up the cluster.</p>
<p>The monitor, keyboard and optionally the mouse can be connected to the master node; however, note that these have to be removed and reconnected to the other computers as well.</p>
<h3 id="heading-2-installing-the-operating-system">2. Installing the Operating System</h3>
<p>The best way to install the operating system on the hardware is to use a bootable USB stick. Use a separate computer and download the ISO of the installer of the preferred Linux OS, in the case of this tutorial, <a target="_blank" href="https://releases.ubuntu.com/22.04.2/ubuntu-22.04.2-live-server-amd64.iso">Ubuntu Server 22.04.2</a> is used as previously mentioned.</p>
<p>Also, download the <a target="_blank" href="https://rufus.ie/en/">Rufus</a> bootable USB tool. In this example <a target="_blank" href="https://rufus.ie/downloads/">Rufus Version 3.22 (Build 2009)</a> is used, however, the version number has little to no effect on the setup. Other bootable USB creators can also be used.</p>
<p>Open Rufus and choose the preferred USB device under <em>Device</em>. Then click on '<em>Boot Selection'</em> and choose <em>Disk or ISO image (Please select)</em> and click on <em>SELECT</em> to choose the ISO file. Navigate to the ISO file and choose it. Other options should be left at default and click on <em>START</em>. For the warning, click <em>OK</em> although note that this process formats the pen drive and all data currently in it will be lost. For the next page, keep the defaults and click on <em>OK</em> as well. This will start the process of formatting the device into a bootable pen drive. Wait for this process to complete and remove the pen drive.</p>
<p>Next, we should install the OS on the hardware. For this, connect the pen drive to each computer one after the other and install the OS. In certain computers, when booting the OS in EFI mode will result in installation errors. In cases like this, try switching to Legacy BIOS before continuing with the installation. The steps involved might change from computer to computer on how to switch to '<em>Legacy mode</em>' and how to enter the boot menu. Please refer online for the specific models.</p>
<p>The installation steps are normal. In all of the steps, the defaults will work fine. On each page, highlight the option <em>Done</em>. It is not essential to set up the network as this will be done in a future step. Downloading additional packages is also not necessary. Following the steps in <a target="_blank" href="https://ubuntu.com/server/docs/install/step-by-step">this tutorial</a> will be sufficient. In the <strong>Identity</strong> screen, however, under '<em>Your name:'</em>, '<em>Your server name:'</em> and '<em>Pick a username:'</em>; enter the following:</p>
<ul>
<li><p>'<strong>master</strong>' for the computer you wish to use as the main computer of the cluster</p>
</li>
<li><p>'<strong>node1</strong>', '<strong>node2</strong>', '<strong>node3</strong>', etc. for the rest of the computers</p>
</li>
</ul>
<p>It is not essential to follow this naming convention but will help identify the computers individually. For the '<em>Choose your password:'</em> and '<em>Confirm your password:'</em>, enter a common password for all computers. This will help keep consistency although it's not essential to have the same password in all computers. Once the installation is complete, select <em>Reboot</em>. Every time the computers are turned on, enter the computer name and password to log in to the computers.</p>
<h2 id="heading-5-setting-up-the-beowulf-cluster">5. Setting up the Beowulf Cluster</h2>
<h3 id="heading-1-introduction-1">1. Introduction</h3>
<p>As mentioned before, the Beowulf cluster is a computer cluster made up of open-source components. Thus to set it up, the following components need to be set up in the computers.</p>
<ul>
<li><p>Message Passing Interface</p>
</li>
<li><p>Network File System</p>
</li>
<li><p>Hydra Process Manager</p>
</li>
</ul>
<p>Make sure all the previous steps are followed correctly and that you have all of the computers ready with Ubuntu Server (or any other Linux distro) installed.</p>
<h3 id="heading-2-setting-up-the-ip-addresses">2. Setting Up the IP addresses</h3>
<p>To continue, each computer must have a unique static IP address. For example, in our case, we will use the IP address of the <em>master</em> as <em>192.168.1.5</em>, <em>node1</em> as <em>192.168.1.6</em>, <em>node2</em> as <em>192.168.1.7</em>, etc. It is not mandatory to use these exact IP addresses but using a consistent IP address assigning might come in handy. Make sure you remember which computer has which IP address.</p>
<p>To set up static IP addresses, first, make sure that all computers are correctly connected via ethernet to the router/switch. If this is confirmed, continue with the setup process. The below steps have to be performed on all the computers, thus disconnect and connect the keyboard and monitor to each computer and continue them.</p>
<ol>
<li><p>Enter the command <code>ip a</code> on the terminal of each computer. This will list all the network interfaces connected to the computer. Find the one connecting the computer to the router/switch. Usually, this might be labelled as eno0, eno1, enp0s25 or eth0.</p>
</li>
<li><p>Once identified, move to the folder <code>/etc/netplan</code>. (Use the command <code>cd /etc/netplan</code>) Once in this folder, check if a file named <code>99_config.yaml</code> or similar exists. (Use the command <code>ls</code>) If so open this using <strong>Nano</strong> or any other text editor. If it doesn't exist, create a file named <code>99_config.yaml</code>. (Use the command <code>sudo nano 99_config.yaml</code>) Enter the below information in the file.</p>
</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">network:</span>
  <span class="hljs-attr">version:</span> <span class="hljs-number">2</span>
  <span class="hljs-attr">renderer:</span> <span class="hljs-string">networkd</span>
  <span class="hljs-attr">ethernets:</span>
    <span class="hljs-attr">eno0:</span>
      <span class="hljs-attr">addresses:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.5</span><span class="hljs-string">/24</span>
      <span class="hljs-attr">routes:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">to:</span> <span class="hljs-string">default</span>
          <span class="hljs-attr">via:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span>
      <span class="hljs-attr">nameservers:</span>
          <span class="hljs-attr">search:</span> [<span class="hljs-string">mydomain</span>, <span class="hljs-string">otherdomain</span>]
          <span class="hljs-attr">addresses:</span> [<span class="hljs-number">10.10</span><span class="hljs-number">.10</span><span class="hljs-number">.1</span>, <span class="hljs-number">1.1</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span>]
</code></pre>
<p>Under <code>addresses:</code>, include the IP address to be assigned for that particular computer. In this example, we've included the IP address we provided for the <em>master</em>. Under <code>routes:</code>, next to <code>via:</code>, include the IP address of the router. This is typically <strong>192.168.1.1</strong>.</p>
<ol>
<li><p>After completion, exit the text editor while saving the file. (<em>Ctrl + X -&gt; Y -&gt; Enter</em> for nano)</p>
</li>
<li><p>Use the command <code>sudo netplan apply</code> to apply the configuration.</p>
</li>
<li><p>On each computer, enter the command <code>ping 192.168.1.5</code> where the IP address is to be replaced by the IP addresses of other nodes. Try for each node to each of the other nodes. If the configuration is correctly performed, you will receive a ping. If not, go through the steps and see if all of them are done correctly and that the network is set up correctly. A reason why this might fail is because the firewall refuses the connection. In that case, try disabling the firewall.</p>
</li>
<li><p>The next step is to add the hostnames to the <code>hosts</code> file. For this, move to the <code>/etc</code> folder. Edit the <code>hosts</code> file. Make sure the following hosts also exist in this file.</p>
</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>       <span class="hljs-string">localhost</span>
<span class="hljs-number">192.168</span><span class="hljs-number">.42</span><span class="hljs-number">.50</span>   <span class="hljs-string">master</span>
<span class="hljs-number">192.168</span><span class="hljs-number">.42</span><span class="hljs-number">.51</span>   <span class="hljs-string">node1</span>
<span class="hljs-number">192.168</span><span class="hljs-number">.42</span><span class="hljs-number">.52</span>   <span class="hljs-string">node2</span>
</code></pre>
<p>The IP addresses must match the IP address of the relevant node. Add all of the nodes you have here.</p>
<h3 id="heading-3-creating-the-mpi-user">3. Creating the MPI User</h3>
<p>A common user must exist across all computers to facilitate communication. For this reason, we will create a user called <code>mpiuser</code> across all the computers. This username as well as the UUID must be common to facilitate with the SSH authorization. Use the following command to create a user on all computers.</p>
<pre><code class="lang-bash">sudo adduser mpiuser --uid 999
</code></pre>
<p>If the UUID 999 is already taken, do the same command but with a different number. However, make sure that the same UUID is provided across all computers for this user. Also, make sure to include a number equal to or more than 999. Make sure to use a consistent password to avoid confusion. (Note that for certain commands, you might need to switch back to the main account; for example, commands that require <code>sudo</code> privileges. Entering the command <code>exit</code> will switch you back to the main account.)</p>
<h3 id="heading-4-setting-up-the-network-file-system-nfs">4. Setting up the Network File System (NFS)</h3>
<p>Network File System (NFS) is a distributed file system protocol that allows a user on a client computer to access files over a network as if those files were on the local computer. With NFS, a user can browse the remote file system, read and write files, and even execute programs located on the remote server. This makes it possible for multiple users to share files and collaborate on projects from different locations.</p>
<p>For this, the computers require an internet connection. If not, connect each computer to the internet and continue the steps. It is ok to disconnect the computers from the router/switch if required. Complete the steps and reconnect to the router/switch.</p>
<p>Use <code>sudo apt-get update</code> and <code>sudo apt-get upgrade</code> to get the app list and apps up to date. Then install NFS as explained below.</p>
<p>For the <em>master</em> node, enter the below command.</p>
<pre><code class="lang-bash">sudo apt-get install nfs-kernel-server
</code></pre>
<p>For the rest of the nodes, use the below command.</p>
<pre><code class="lang-bash">sudo apt-get install nfs-common
</code></pre>
<p>This will install the relevant NFS package on each computer.</p>
<h3 id="heading-5-sharing-the-home-folder">5. Sharing the Home folder</h3>
<p>Across all the computers, the <code>/home/mpiuser</code> directory has to be shared via NFS. For this, the <code>/home/mpiuser</code> directory has to be owned by the <em>mpiuser</em>. However, this folder is already created while adding the user, which means that the <em>mpiuser</em> already has access to it. To verify this, the following command can be used.</p>
<pre><code class="lang-bash">master:~$ ls -l /home/ | grep mpiuser
</code></pre>
<p>If the folder is already owned by the mpiuser, this should return a message similar to below.</p>
<pre><code class="lang-yaml"><span class="hljs-string">drwxr-xr-x</span> <span class="hljs-number">7</span> <span class="hljs-string">mpiuser</span> <span class="hljs-string">mpiuser</span> <span class="hljs-number">4096 </span><span class="hljs-string">May</span> <span class="hljs-number">30</span> <span class="hljs-number">05</span><span class="hljs-string">:55</span> <span class="hljs-string">mpiuser</span>
</code></pre>
<p>If you want to share some other folder, use the below command on the <em>master</em> node with the specific folder you need to share.</p>
<pre><code class="lang-bash">sudo chown mpiuser:mpiuser /path/to/shared/dir
</code></pre>
<p>Now, the <code>/home/mpiuser</code> or any other folder created before the <em>master</em> node needs to be shared with the rest of the nodes. For this, the relevant folder needs to be added to the <code>/etc/exports</code> file. To do this, navigate to the <code>/etc</code> folder. (Use the command <code>cd /etc</code>) Now edit the file with the text editor (Use the command <code>sudo nano exports</code>) and add the following entry to it. This should only be done in the <em>master</em> node.</p>
<pre><code class="lang-yaml"><span class="hljs-string">/home/mpiuser</span> <span class="hljs-string">*(rw,sync,no_subtree_check)</span>
</code></pre>
<p>Once done, save the file, (<em>Ctrl + X -&gt; Y -&gt; Enter</em> for nano) and then restart the NFS kernel using the below command.</p>
<pre><code class="lang-bash">sudo service nfs-kernel-server restart
</code></pre>
<p>To check if the folder is shared correctly, use the following command on the master node.</p>
<pre><code class="lang-bash">showmount -e master
</code></pre>
<p>If correctly performed, this should print the folder <code>/home/mpiuser</code> or the relevant folder on the terminal.</p>
<p>The next step is to check if it's accessible to the other nodes. Before that, we need to make sure the firewall doesn't block the communications between computers. For this, you can either disable the firewall or enter the following command on all computers. The IP address should be the gateway address. (*<a target="_blank" href="http://xxx.xxx.xxx">xxx.xxx.xxx</a>.0/24)</p>
<pre><code class="lang-bash">sudo ufw allow from 192.168.1.0/24
</code></pre>
<p>Once complete, check the connectivity with the <code>ping</code> command used before.</p>
<p>Now, we can mount the shared folder on other nodes. For this, we use the below command on all nodes.</p>
<pre><code class="lang-bash">sudo mount master:/home/mpiuser /home/mpiuser
</code></pre>
<p>If this command hangs or fails, there's an issue with the configuration. If the command succeeds, test if the folder is shared across all nodes. For this, you can create a file in the <code>/home/mpiuser</code> directory of the <em>master</em> and see if it appears in the rest of the nodes. (Use the command <code>touch hello</code> to create a file)</p>
<p>If everything is correct so far, we have to set up the nodes to automatically mount this folder at boot. For this, move to the folder <code>/etc/</code>, (Use the command <code>cd /etc/</code>) then edit the file <code>fstab</code> on all computers. (Use the command <code>sudo nano fstab</code>) Add the below entry to this file.</p>
<pre><code class="lang-yaml"><span class="hljs-string">master:/home/mpiuser</span> <span class="hljs-string">/home/mpiuser</span> <span class="hljs-string">nfs</span>
</code></pre>
<p>Now reboot all computers and see if the system is correctly working, for example, the <code>hello</code> file is accessible from all nodes.</p>
<h3 id="heading-6-setting-up-the-secure-shell-ssh">6. Setting up the Secure Shell (SSH)</h3>
<p>SSH (Secure Shell) is a cryptographic network protocol that provides a secure way to access remote systems over an unsecured network. It was developed as a replacement for Telnet and other insecure remote shell protocols. To continue, SSH has to be set up on all computers.</p>
<p>Connect each computer to the internet and use the following command to install SSH.</p>
<pre><code class="lang-bash">sudo apt-get install ssh
</code></pre>
<p>Once done on all computers, SSH keys need to be generated under the <em>mpiuser</em> for all computers. Since the home folder is shared across all computers, these keys will be accessible to the <em>master</em>. On each computer, switch to the <em>mpiuser</em>, (Use the command <code>su mpiuser</code>) and then enter the following command.</p>
<pre><code class="lang-bash">ssh-keygen
</code></pre>
<p>When asked for a passphrase, leave it empty (hence passwordless SSH). Now switch to the master node and enter the following command under <em>mpiuser</em>.</p>
<pre><code class="lang-bash">ssh-copy-id localhost
</code></pre>
<p>If done correctly, you will get a message that says something similar to '<em>Number of key (s) added: 3</em>'.</p>
<p>If configured correctly, now you might be able to SSH into any of the <em>nodes</em> from the <em>master</em>. Try to use the below command to enter into SSH from <em>master</em> to <em>node1</em>.</p>
<pre><code class="lang-bash">ssh node1
</code></pre>
<p>This should change the prompt from <code>mpiuser@master:~$</code> to <code>mpiuser@node1:~$</code> . This means that all commands executed will be executed inside of the <em>mpiuser</em> of node1. For example, the command <code>echo $HOSTNAME</code>, will print <code>node1</code> instead of <code>master</code>. An advantage of this setup is that by using the command <code>systemctl -i poweroff</code>, you can shut down each computer remotely when SSH into the specific node. The same should apply to all other nodes.</p>
<h3 id="heading-7-setup-hydra-process-manager">7. Setup Hydra Process Manager</h3>
<p>Hydra is a process management system used to manage and monitor processes on a Unix or Linux system. It is designed to be simple to use and can be used to start, stop, and monitor multiple processes at once. Hydra consists of two main components: a daemon process that runs in the background and a command-line interface that allows users to manage processes. The daemon process is responsible for starting and stopping processes, monitoring their status, and responding to commands from the command-line interface.</p>
<p>The Hydra Process Manager is included with the MPICH package, so we need to install MPICH on all computers. To do this, switch between each computer and use the following command to install it. To do this, make sure that the computer is connected to the internet.</p>
<pre><code class="lang-bash">sudo apt-get install mpich
</code></pre>
<p>This should install MPICH on all nodes. Once done, network all computers to the correct configuration and continue.</p>
<p>The next step is to configure MPICH. To do this, switch to the <em>master</em> and switch to <em>mpiuser</em>. (Use the command <code>su mpiuser</code>) Once in the <em>mpiuser</em>, move to the home directory. (Use the command <code>cd ~</code>) Now use a text editor to create a file called <code>hosts</code>, (Use the command <code>nano hosts</code> for <em>nano</em>) and enter the hostnames of the nodes you want the processes to run. You can either include the <em>master</em> node as a computer node or only use the other nodes. For example, refer to below. Once done, save the file. (<em>Ctrl + X -&gt; Y -&gt; Enter</em> for nano)</p>
<pre><code class="lang-yaml"><span class="hljs-string">master</span>
<span class="hljs-string">node1</span>
<span class="hljs-string">node2</span>
</code></pre>
<p>The above example will run the programs distributed across <em>master</em>, <em>node1</em> and <em>node2</em>.</p>
<h2 id="heading-6-running-a-sample-program">6. Running a Sample Program</h2>
<h3 id="heading-1-simple-mpi-program-in-c">1. Simple MPI Program in C</h3>
<p>To write a simple MPI-based program in C, we will first create the source code. For this, we will switch to the <em>mpiuser</em> (Use the command <code>su mpiuser</code>) and move it into the home folder. (Use the command <code>cd ~</code>) Here, we will create a new file. (Use the command <code>nano hello.c</code>)</p>
<p>In it, we will write the following sample code.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;mpi.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>** argv)</span> </span>{
    <span class="hljs-comment">// Initialize the MPI environment</span>
    MPI_Init(<span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);

    <span class="hljs-comment">// Get the number of processes</span>
    <span class="hljs-keyword">int</span> world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &amp;world_size);

    <span class="hljs-comment">// Get the rank of the process</span>
    <span class="hljs-keyword">int</span> world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &amp;world_rank);

    <span class="hljs-comment">// Get the name of the processor</span>
    <span class="hljs-keyword">char</span> processor_name[MPI_MAX_PROCESSOR_NAME];
    <span class="hljs-keyword">int</span> name_len;
    MPI_Get_processor_name(processor_name, &amp;name_len);

    <span class="hljs-comment">// Print off a hello world message</span>
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Hello world from processor %s, rank %d out of %d processors\n"</span>,
           processor_name, world_rank, world_size);

    <span class="hljs-comment">// Finalize the MPI environment.</span>
    MPI_Finalize();
}
</code></pre>
<p>The code is designed to print the node names and their ranks on the terminal of the <em>master</em>.</p>
<p>The next step is to compile the code into an object file. For this, use the following command.</p>
<pre><code class="lang-bash">mpicc -o hello.o hello.c
</code></pre>
<p>This will compile the code into an object file. Now we can run the MPI program on the cluster. For this, enter the following code.</p>
<pre><code class="lang-bash">mpiexec -n 12 -f hosts hello.c
</code></pre>
<p>Here, <code>-n 12</code> defines that the process should run on 12 threads and that <code>-f hosts</code> define the file which contains the list of nodes to run the program on.</p>
<p>If working correctly, it should print a result as below.</p>
<pre><code class="lang-bash">Hello world from processor 1, rank 1 out of 12 processors
Hello world from processor 5, rank 5 out of 12 processors
Hello world from processor 3, rank 3 out of 12 processors
Hello world from processor 2, rank 2 out of 12 processors
Hello world from processor 8, rank 8 out of 12 processors
Hello world from processor 4, rank 4 out of 12 processors
Hello world from processor 6, rank 6 out of 12 processors
Hello world from processor 7, rank 7 out of 12 processors
Hello world from processor 9, rank 9 out of 12 processors
Hello world from processor 10, rank 10 out of 12 processors
Hello world from processor 12, rank 12 out of 12 processors
Hello world from processor 11, rank 11 out of 12 processors
</code></pre>
<h3 id="heading-2-simple-mpi-program-in-python">2. Simple MPI Program in Python</h3>
<p>It is also possible to run an MPI program on Python. For this, we will follow the same steps and create a source file, this time named <a target="_blank" href="http://hello.py"><code>hello.py</code></a>. In it, we will write the following code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> mpi4py <span class="hljs-keyword">import</span> MPI

comm = MPI.COMM_WORLD
rank = comm.Get_rank()
name = MPI.Get_processor_name()

print(<span class="hljs-string">'My rank is '</span>, rank, <span class="hljs-string">' and hostname is '</span>, name)
</code></pre>
<p>Once done, save the file and use the following command to run the program.</p>
<pre><code class="lang-bash">mpirun -np 12 --hostfile hosts python3 hello.py
</code></pre>
<p>If you get an error that says that <code>mpi4py</code> library is not installed, install it. (under <em>mpiuser</em>, use the command <code>pip install mpi4py</code>) If you get an error that says something similar to <strong>Permission Denied</strong>, use the command <code>chmod +rwx ~</code> under <em>mpiuser</em> to mark the home folder and its content as executable. Retry running the command again.</p>
<p>You should get an output similar to below.</p>
<pre><code class="lang-bash">My rank is 1 and hostname is master
My rank is 3 and hostname is master
My rank is 2 and hostname is master
My rank is 4 and hostname is master
My rank is 5 and hostname is node1
My rank is 6 and hostname is node1
My rank is 8 and hostname is node1
My rank is 9 and hostname is node2
My rank is 7 and hostname is node1
My rank is 10 and hostname is node2
My rank is 11 and hostname is node2
My rank is 12 and hostname is node2
</code></pre>
<h2 id="heading-7-conclusion">7. Conclusion</h2>
<p>In conclusion, a Beowulf cluster is a type of high-performance computing cluster that is built from commodity hardware and is designed to run parallel computing applications. The Beowulf cluster architecture is based on a master-slave model, where a central master node manages the workload and distributes tasks to multiple slave nodes.</p>
<p>MPI (Message Passing Interface) is a standard interface for programming parallel applications on a Beowulf cluster. It allows processes to communicate with each other and synchronize their actions across multiple nodes. MPI provides a set of standard libraries and functions that can be used to develop scalable and efficient parallel applications.</p>
<p>Together, a Beowulf cluster and MPI provide a powerful platform for running large-scale parallel applications. They can be used for a wide range of applications, including scientific simulations, data processing, and machine learning. The scalability and flexibility of these systems make them an ideal choice for organizations and research institutions that require high-performance computing capabilities.</p>
<h2 id="heading-8-reference">8. Reference</h2>
<ul>
<li><p><a target="_blank" href="https://ubuntu.com/server/docs/network-configuration">https://ubuntu.com/server/docs/network-configuration</a></p>
</li>
<li><p><a target="_blank" href="https://mpitutorial.com/tutorials/mpi-hello-world/">https://mpitutorial.com/tutorials/mpi-hello-world/</a></p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/32257375/how-to-run-a-basic-mpi4py-code">https://stackoverflow.com/questions/32257375/how-to-run-a-basic-mpi4py-code</a></p>
</li>
<li><p><a target="_blank" href="https://www.open-mpi.org/doc/current/man1/mpirun.1.php">https://www.open-mpi.org/doc/current/man1/mpirun.1.php</a></p>
</li>
<li><p><a target="_blank" href="https://www.programcreek.com/python/example/89108/mpi4py.MPI.Get_processor_name">https://www.programcreek.com/python/example/89108/mpi4py.MPI.Get_processor_name</a></p>
</li>
<li><p><a target="_blank" href="https://rabernat.github.io/research_computing/parallel-programming-with-mpi-for-python.html">https://rabernat.github.io/research_computing/parallel-programming-with-mpi-for-python.html</a></p>
</li>
<li><p><a target="_blank" href="http://cs.boisestate.edu/~amit/research/beowulf/lab-notes/node19.html">http://cs.boisestate.edu/~amit/research/beowulf/lab-notes/node19.html</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/jbornschein/mpi4py-examples">https://github.com/jbornschein/mpi4py-examples</a></p>
</li>
<li><p><a target="_blank" href="https://gist.github.com/arifsisman/bcb6409fcb6150099cb8ddd044e28060">https://gist.github.com/arifsisman/bcb6409fcb6150099cb8ddd044e28060</a></p>
</li>
<li><p><a target="_blank" href="https://rabernat.github.io/research_computing/parallel-programming-with-mpi-for-python.html">https://rabernat.github.io/research_computing/parallel-programming-with-mpi-for-python.html</a></p>
</li>
<li><p><a target="_blank" href="https://blogs.cisco.com/performance/tree-based-launch-in-open-mpi">https://blogs.cisco.com/performance/tree-based-launch-in-open-mpi</a></p>
</li>
<li><p><a target="_blank" href="https://blogs.cisco.com/performance/tree-based-launch-in-open-mpi-part-2">https://blogs.cisco.com/performance/tree-based-launch-in-open-mpi-part-2</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>