<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>linux on tkainrad</title>
    <link>https://tkainrad.dev/tags/linux/</link>
    <description>Recent content in linux on tkainrad</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sun, 05 Jan 2020 00:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://tkainrad.dev/tags/linux/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Managing my personal knowledge base</title>
      <link>https://tkainrad.dev/posts/managing-my-personal-knowledge-base/</link>
      <pubDate>Sun, 05 Jan 2020 00:00:00 +0000</pubDate>
      
      <guid>https://tkainrad.dev/posts/managing-my-personal-knowledge-base/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;It is hard to imagine any other field where lifelong learning is more important than in software engineering. Another unique characteristic is the degree to which learning material is available for free on the internet. On top of that, we create various resources ourselves by documenting issues, submitting bug reports, writing notes, creating documentation, and many others. The sum of all these resources can be called a knowledge base.
You could argue that every developer has a system to manage their personal knowledge base, whether they know it or not. In this post, I explain my knowledge management practices.&lt;/p&gt;

&lt;div class=&#34;notices warning&#34;&gt;
    &lt;p&gt;A software engineer&amp;rsquo;s personal knowledge base is likely to overlap with the knowledge of their employers and project partners. Be sure to carefully study your data protection obligations. A good basis is to keep your personal knowledge base strictly technical and to never include data that is related to customers, or people in general.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;I chose this topic mainly because of three reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fun:&lt;/strong&gt;&lt;br&gt;
I enjoy thinking about my workflows and trying to improve them. Maybe a little too much, some friends have started to roll their eyes when I try to recommend a new tool to them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improving my system and workflows:&lt;/strong&gt;&lt;br&gt;
Writing &lt;a href=&#34;https://tkainrad.dev/posts/setting-up-linux-workstation/&#34;&gt;a post about my Linux setup&lt;/a&gt; has been very rewarding for me. While documenting my configuration, especially my command-line workflows, I identified some shortcomings that I have since eliminated. After writing this article, I can already say that my knowledge management workflows have improved similarly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Relevance:&lt;/strong&gt;&lt;br&gt;
Knowledge management in all its forms is integral to software engineering.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://imgs.xkcd.com/comics/is_it_worth_the_time.png&#34;
         alt=&#34;Knowledge management tasks are done frequently. It pays off to do them efficiently. (Source: xkcd.com)&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Knowledge management tasks are done frequently. It pays off to do them efficiently. (Source: xkcd.com)&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Much of this post comes down to describing my usage of software tools. The stars will be&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.notion.so/?r=cb45b9cefd824015a044b3336009be32&#34;&gt;Notion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/&#34;&gt;GitLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://workona.com/&#34;&gt;Workona&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/&#34;&gt;Dropbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/albertlauncher/albert&#34;&gt;Albert&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;Copying all of my practices will likely not serve you well. I invite you to try out things at your own pace and revisit this post whenever you are looking for new ideas.&lt;/p&gt;

&lt;/div&gt;
&lt;h1 id=&#34;bookmarking&#34;&gt;Bookmarking&lt;/h1&gt;
&lt;p&gt;Even though everybody loves books, or at least says so, myself included, the reality is that we rely on digital resources most of the time.
The challenge is to organize this knowledge efficiently without creating too much overhead.&lt;/p&gt;
&lt;p&gt;There are some naive approaches that I do not deem sufficient. Until a few years ago, I relied mainly on browser bookmarks, but for some reason, browsers do not provide proper organizing features.
Another way is to just copy the URLs into notes, project issues, documentation and all other kinds of manually created content. This is viable and we all do it regularly, but it has nothing to do with what I think is bookmark management.&lt;/p&gt;
&lt;p&gt;My current setup is a little more complex, but in the end, it does not require more work than keeping bookmarks solely in the browser.
I organize my bookmarks in multiple layers, depending on how often I want to access them and how long they should persist.&lt;/p&gt;
&lt;p&gt;Maybe you are thinking of caching now, but fortunately, bookmarking layers are not caching levels. This would be hard to manage because as we all know, there are &lt;a href=&#34;https://martinfowler.com/bliki/TwoHardThings.html&#34;&gt;two hard problems in computer science&lt;/a&gt;: cache invalidation, naming things, and off-by-1 errors.
In contrast to cache entries, a bookmark is not supposed to move between layers. Instead, it gets inserted at the right place and stays there.&lt;/p&gt;
&lt;p&gt;The following figure illustrates my layers:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/bookmarking-layers.png&#34;
         alt=&#34;Bookmarking layers&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Bookmarking layers&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;1-chrome-bookmarks&#34;&gt;1. Chrome Bookmarks&lt;/h2&gt;
&lt;p&gt;Chrome bookmarks have some nice benefits. They are synchronized between devices, new ones can be added easily, and organizing them in folders brings at least some structure. Another advantage for me is the &lt;a href=&#34;https://albertlauncher.github.io/docs/extensions/chromium/&#34;&gt;Albert Chromium extension&lt;/a&gt; that lets me access and open my Chrome bookmarks from Albert:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/albert-chrome-bookmarks.gif&#34;
         alt=&#34;Searching through Chrome bookmarks directly from Albert. Pressing enter opens the selected entry in Chrome.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Searching through Chrome bookmarks directly from Albert. Pressing enter opens the selected entry in Chrome.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Because of these advantages, Chrome bookmarks are ideal for things that I need often and want to have accessible somewhat independent of context. They are, however, not well suited for keeping extensive bookmark libraries. There is no tagging, it is not possible to add comments, and browsers do not even save a timestamp for when a page was bookmarked. It is further not possible to filter and search Chrome bookmarks using complex queries. In my experience, browser bookmark libraries are hard to manage if they grow beyond a certain size.&lt;/p&gt;
&lt;p&gt;Some examples of well-suited Chrome bookmarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS EC2 dashboard&lt;/li&gt;
&lt;li&gt;Google cloud platform console&lt;/li&gt;
&lt;li&gt;Slack workspaces&lt;/li&gt;
&lt;li&gt;GitLab boards&lt;/li&gt;
&lt;li&gt;Content sites, such as &lt;a href=&#34;https://news.ycombinator.com/&#34;&gt;Hacker News&lt;/a&gt;, &lt;a href=&#34;https://www.infoq.com/&#34;&gt;InfoQ&lt;/a&gt;, and &lt;a href=&#34;https://dzone.com/&#34;&gt;DZone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Examples of things that &lt;strong&gt;should not be&lt;/strong&gt; Chrome bookmarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blog posts to be read later&lt;/li&gt;
&lt;li&gt;Links to Open Source Projects&lt;/li&gt;
&lt;li&gt;Stack Overflow questions&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;2-workona&#34;&gt;2. Workona&lt;/h2&gt;
&lt;p&gt;Workona is a relatively new addition to my toolbox. I have mixed feelings about it, mainly because it can feel a little slow at times.
There are some things it does very well though.&lt;/p&gt;
&lt;p&gt;Workona lets you create browser workspaces that come with their own list of bookmarks. This works nicely when you have multiple projects that you work on for longer periods. It will also remember which tabs you had open in a specific workspace and synchronize this information across devices. It is, therefore, a nice place for things that I need often &lt;em&gt;dependent&lt;/em&gt; on context.&lt;/p&gt;
&lt;figure class=&#34;&amp;#39;center-figure&amp;#39;&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/workona-workspace.jpg&#34;
         alt=&#34;Screenshot of a Workona Workspace (Source)&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Screenshot of a Workona Workspace (&lt;a href=&#34;https://workona.com/tour/&#34;&gt;Source&lt;/a&gt;)&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Workona further allows you to add apps and will then collect links and even features for those apps to be quickly accessible. For example, I use it to access my different GitLab and GitHub projects, Slack Workspaces, and sometimes even StackOverflow questions. These entries are automatically created by Workona and therefore I do not see them as bookmarks. It is also possible to access features of these apps directly from Workona, mainly to create new resources, such as GitLab/GitHub projects, Google Docs, DropBox Files and so on. It feels a little bit like &lt;a href=&#34;https://getstation.com/&#34;&gt;Station&lt;/a&gt; built directly into the browser.&lt;/p&gt;
&lt;p&gt;The selling point for me is that Workona &lt;strong&gt;lets me do all of the described things via shortcuts&lt;/strong&gt; and it is even possible to customize these shortcuts at &lt;code&gt;chrome://extensions/shortcuts&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;3-notion&#34;&gt;3. Notion&lt;/h2&gt;
&lt;p&gt;Finally, we arrive at the layer that is suited for maintaining a large library of bookmarks. For this, and many other use cases, I use &lt;a href=&#34;https://www.notion.so/?r=cb45b9cefd824015a044b3336009be32&#34;&gt;Notion&lt;/a&gt;. It has become the core of my personal knowledge base.&lt;/p&gt;

&lt;div class=&#34;notices warning&#34;&gt;
    &lt;p&gt;Notion&amp;rsquo;s free tier comes with a hard limit on the number of blocks you can create. This means that you will have to switch to the paid version if you use it seriously for a while. It is free for &lt;a href=&#34;https://www.notion.so/Notion-for-students-teachers-adc631df15ee4ab9a7a33dd50f4c16fe&#34;&gt;students and teachers&lt;/a&gt;.&lt;br&gt;
All links to Notion in this post are affiliate links. If you sign up for an account through these links, you will get 10$ of free Notion credit and I will get 5$. This works even if you create a free account.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;The killer feature for me is the database. It is amazingly flexible and is single-handedly able to replace multiple other tools for me. For my bookmark collection, I use a single large database. Adding new items can be done via the &lt;a href=&#34;https://chrome.google.com/webstore/detail/notion-web-clipper/knheggckgoiihginacbkhaalnibhilkk&#34;&gt;Notion Web Clipper&lt;/a&gt;. I am a little annoyed that the web clipper doesn&amp;rsquo;t let me add properties and tags directly, but other than that, it works well. Previously, I used Trello, which was also quite good at keeping bookmarks. However, to limit the number of different tools I use, I replaced it with Notion.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/notion-bookmark-database.png&#34;
         alt=&#34;My bookmarks database filtered to show only entries related to this post.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;My bookmarks database filtered to show only entries related to this post.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The goal with this database is that I can find something years from now with only a vague memory that it should be there. This is possible because Notion automatically stores metadata, such as a creation timestamp. Even more important, I can add tags and arbitrary properties.&lt;/p&gt;
&lt;p&gt;Things get really exciting once you use relations between different Notion databases. As an example, I have a database of my blog posts that has a relation to my bookmarks. I can now filter my bookmarks by blog posts and quickly see which sources influenced a particular post.&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;I cannot cover all Notion database features in this post. I think this is something you have to see for yourself. The &lt;a href=&#34;https://www.notion.so/Intro-to-databases-fd8cd2d212f74c50954c11086d85997e&#34;&gt;Notion docs page about the topic&lt;/a&gt; might give you some further impressions though.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;The downside of this rich feature palette is that it requires some discipline. I tag and annotate new entries, that I added via the web clipper, about twice a month. Often, I just delete new items because they do not seem important anymore. If I can not think of appropriate tags or relations for an item, this often means that it is not very relevant to me.&lt;/p&gt;
&lt;p&gt;Another important lesson I had to learn the hard way:&lt;br&gt;
Do not use too many databases in parallel. Notion provides excellent methods for filtering, and searching tables. You can even define different views onto the same database that only shows a specific part of the data. It is therefore not required to separate all kinds of things into different databases. For example, at first, I had three different databases for Python resources, Django resources, and Wagtail resources. This was a bad solution. Now, these all live in the same database with appropriate tags.&lt;/p&gt;
&lt;p&gt;I hope that someday I will be able to search through my Notion databases from &lt;a href=&#34;https://github.com/albertlauncher/albert&#34;&gt;Albert&lt;/a&gt;. Maybe I will build an extension myself once the Notion API is finally released.&lt;/p&gt;
&lt;p&gt;To illustrate what I have described in probably too many words, you can have a look at a &lt;a href=&#34;https://www.notion.so/tkpersonal/047517457f70471a91a9dac793b8d51b?v=802c2ec373fa43d0b7caf16ed8bfccda&#34;&gt;public fraction of my bookmarks database&lt;/a&gt; containing all the resources that were helpful for writing this post. The post-column in this public database appears empty because the related table is not public.&lt;/p&gt;
&lt;h2 id=&#34;4-native-bookmark-sources&#34;&gt;4. Native Bookmark Sources&lt;/h2&gt;
&lt;p&gt;The last layer does not require any work at all. It only means to be aware of native bookmark sources when trying to find something, and also when thinking about adding new bookmarks. For example, it is quite easy to search through questions you have answered on Stack Overflow. It is also not a problem to go back to your Hacker News posts or search through projects you starred on GitHub. Keeping those things in your own bookmark sources adds redundancy and noise.&lt;br&gt;
These are some of my most commonly used native bookmark sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://news.ycombinator.com/&#34;&gt;https://news.ycombinator.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/&#34;&gt;https://twitter.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/&#34;&gt;https://github.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/&#34;&gt;https://gitlab.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tkainrad.dev/posts/&#34;&gt;https://tkainrad.dev/posts/&lt;/a&gt; ;-)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I am aware that this sounds immensely complicated. However, I stick to my statement that it does not actually require more work than keeping all bookmarks in the browser. You still have to add every bookmark only once. If you internalize your system, you will not have problems searching for bookmarks as it will be quite obvious where a specific resource could be. Admittedly, it does require some maintenance to keep a large bookmark collection in Notion, but it pays off soon and the pay-off accumulates over time.&lt;/p&gt;
&lt;h1 id=&#34;organizing-self-written-resources&#34;&gt;Organizing Self-Written Resources&lt;/h1&gt;
&lt;p&gt;Having a proper system for external resources is great, but it does not help much if everything you write yourself is a mess. Therefore, it is essential to organize self-written resources.&lt;/p&gt;
&lt;h2 id=&#34;blog-posts&#34;&gt;Blog Posts&lt;/h2&gt;
&lt;p&gt;My most successful blog post is about &lt;a href=&#34;https://tkainrad.dev/posts/using-hugo-gitlab-pages-and-cloudflare-to-create-and-run-this-website/&#34;&gt;how I run and host this website for free&lt;/a&gt;. However, the post does not cover the most work-intensive part about running this site: Writing and maintaining blog posts. For this, I heavily rely on Notion. I have a database with all my past blog posts and ideas for future posts. It is simple to add tags like &lt;code&gt;done&lt;/code&gt;, &lt;code&gt;doing&lt;/code&gt;, &lt;code&gt;idea&lt;/code&gt;, and to view the database as a kanban board with lanes based on those tags.&lt;/p&gt;
&lt;h3 id=&#34;drafting-posts&#34;&gt;Drafting Posts&lt;/h3&gt;
&lt;p&gt;All posts that are published on this blog have been drafted in &lt;a href=&#34;https://www.notion.so/?r=cb45b9cefd824015a044b3336009be32&#34;&gt;Notion&lt;/a&gt;. When they are more or less finished, I use the markdown export and copy the content into a new text file in my &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; project. There are some minor issues with this. Usually, I have to adjust code formattings and links, but overall it works very well and has some nice benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Edit on all devices&lt;/strong&gt;&lt;br&gt;
Using notion, I can easily edit my drafts on all devices, even on my phone when I am moving.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use existing notion content&lt;/strong&gt;&lt;br&gt;
I can quickly add code snippets, links, and other stuff that I keep in Notion. This can be done via database relations or just by dragging the respective blocks into the draft page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight version control&lt;/strong&gt;&lt;br&gt;
As developers, we love GIT. However, for adding a couple of lines to a blog post, it is an overkill. Notion has versioning features build-in and keeps track of all changes automatically. Naturally, it does not offer sophisticated merging options, but it&amp;rsquo;s easy to stay clear of conflicts when you are writing a personal blog.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once a post is released, I move the post from &lt;code&gt;doing&lt;/code&gt; to &lt;code&gt;released&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;keeping-track-of-update-ideas&#34;&gt;Keeping Track of Update Ideas&lt;/h3&gt;
&lt;p&gt;You may have noticed that some of my blog posts are quite long. Keeping them up-to-date is a little challenging. Fortunately, I have Notion to assist me with this. I have a database where I add proposals for updating my existing posts. Using a relation, I link these ideas to the respective posts in my posts database:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/notion-blog-update-proposals.png&#34;
         alt=&#34;It is hard to know when you are finished setting up the perfect Linux workstation.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;It is hard to know when you are finished &lt;a href=&#34;https://tkainrad.dev/posts/setting-up-linux-workstation/&#34;&gt;setting up the perfect Linux workstation&lt;/a&gt;.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id=&#34;tracking-sources&#34;&gt;Tracking Sources&lt;/h3&gt;
&lt;p&gt;To keep track of third-party resources that were helpful in creating a post, I add them to my bookmarks database and link them to my posts database.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/notion-blog-sources.png&#34;
         alt=&#34;My bookmarks database filtered to show only entries related to this post.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;My bookmarks database filtered to show only entries related to this post.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;You can also have a look at the full list of sources for this post via a &lt;a href=&#34;https://www.notion.so/tkpersonal/047517457f70471a91a9dac793b8d51b?v=802c2ec373fa43d0b7caf16ed8bfccda&#34;&gt;public fraction of my bookmarks database&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;taking-notes&#34;&gt;Taking Notes&lt;/h2&gt;
&lt;p&gt;I suppose every software engineer takes notes to some extent, even if they do not have a system and just casually write stuff into text files.
There is also a large amount of free and paid software for taking and organizing notes. Some people even like to use physical paper with the &lt;a href=&#34;https://en.wikipedia.org/wiki/Bullet_Journal&#34;&gt;BuJo&lt;/a&gt; system.&lt;/p&gt;
&lt;p&gt;No matter which method you prefer, you have to think about when, why, and how to take notes.&lt;/p&gt;
&lt;h3 id=&#34;when-to-take-notes&#34;&gt;When to take Notes&lt;/h3&gt;
&lt;p&gt;I thought quite a bit about this question, and previously I did not adhere to any predefined rules regarding this matter. To gain a better understanding of my habits and to decide what worked best in the past, I looked through my notes from the last years that were spread over multiple applications and lots of files. I tried to find common patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Capturing information from audio sources&lt;/strong&gt;&lt;br&gt;
I am a visual learner and prefer written content over audio. However, there are many types of audio sources that everybody encounters:
&lt;ul&gt;
&lt;li&gt;Meetings&lt;/li&gt;
&lt;li&gt;Presentations&lt;/li&gt;
&lt;li&gt;Meetups&lt;/li&gt;
&lt;li&gt;Conferences&lt;/li&gt;
&lt;li&gt;Informal Discussions&lt;/li&gt;
&lt;li&gt;Videos&lt;/li&gt;
&lt;li&gt;Podcasts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Preserving information that is often needed but doesn&amp;rsquo;t fit in any proper documentation project&lt;/strong&gt;&lt;br&gt;
In my case, these are things like the following:
&lt;ul&gt;
&lt;li&gt;Command-lines with multiple parameters, complex options, and paths. I keep them in my notes so that I can quickly copy-paste them in the potentially distant future.&lt;/li&gt;
&lt;li&gt;Instructions for tasks that will likely have to be repeated in the future, for example
&lt;ul&gt;
&lt;li&gt;setting up a development environment for a specific tech stack&lt;/li&gt;
&lt;li&gt;deploying a project on a specific hosting service.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Questions&lt;/strong&gt;&lt;br&gt;
Sometimes I think of a question that I would like to ask someone specific, who is not available at the moment. The question and its eventual answer are a nice use case for a note.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;Thanks to a more sophisticated command-line setup with Zsh and various plugins for auto-completion and history-search, preserving command-lines has become much less important for me. If you are still using Bash with its default &lt;code&gt;Ctl&lt;/code&gt; -  &lt;code&gt;r&lt;/code&gt; search, I think you would profit from my &lt;a href=&#34;https://tkainrad.dev/posts/setting-up-linux-workstation/&#34;&gt;post on setting up a Linux workstation&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;On the other hand, it is important to make clear also what &lt;strong&gt;should not be a note&lt;/strong&gt; in this system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project-specific knowledge&lt;/strong&gt;&lt;br&gt;
Everything that is directly related to a specific software project, should not be a note in your personal knowledge base. Instead, it should go into whichever system is used to keep track of issues, merge requests, documentation, and so on. This post includes a &lt;a href=&#34;#project-specific-knowledge&#34;&gt;separate section on this below&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Information that is needed for a very short time&lt;/strong&gt;
Sometimes I need to take notes during a conversation that I will need only immediately afterward. For this, I just open VSCode and type ahead. Once the information is no longer needed, the file can be deleted completely.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In general, don&amp;rsquo;t overdo and don&amp;rsquo;t underdo it. If you take notes all the time, you create overhead and redundancy. If you never take notes, well, you will not have notes.&lt;/p&gt;
&lt;h3 id=&#34;why-take-notes&#34;&gt;Why Take Notes&lt;/h3&gt;
&lt;p&gt;The obvious answer is to remember things. This does not mean that note-taking should replace your memory. To the contrary, taking notes provides structure and context and therefore helps your brain build up a map of your knowledge. I believe that taking notes &lt;em&gt;increases&lt;/em&gt; the amount of data that you can recall from memory.&lt;/p&gt;
&lt;p&gt;Additionally, some things are just very hard to remember, such as complex tech stacks presented at meetups, command-lines with several opaque options, numbers, and so on. Writing these things down can extend your knowledge base significantly. Notes are also very helpful when writing documentation in the future, or for writing blog posts like this one ;-)&lt;/p&gt;
&lt;h3 id=&#34;how-to-take-notes&#34;&gt;How to Take Notes&lt;/h3&gt;
&lt;p&gt;It can be tempting to just type ahead during a talk. Noting down whatever seems interesting at the moment. However, you should meet basic formal requirements and write down some context. Otherwise, you will have trouble extracting useful information from your notes in the future. If you take notes regularly, it is also important to organize them by assigning tags and properties, having a creation date, being able to filter and search through them, and so on. Software can help with these things.&lt;/p&gt;
&lt;p&gt;Until about a year ago I kept notes mainly on my local machines, syncing them with Dropbox. Applications that focus almost exclusively on note-taking, such as &lt;a href=&#34;https://evernote.com/&#34;&gt;Evernote&lt;/a&gt;, never had that much appeal to me, even though I used Google Keep/Notes. It is not so bad, supports e.g. labeling and works with little friction on mobile. However, there is not even basic formatting support, let alone markdown formatting or code syntax highlighting.&lt;/p&gt;
&lt;p&gt;Then, I discovered &lt;a href=&#34;https://www.notion.so/?r=cb45b9cefd824015a044b3336009be32&#34;&gt;Notion&lt;/a&gt;.
At first, It wasn&amp;rsquo;t really about note-taking for me. I liked it mainly because of its database concept and for organizing third-party resources as described in the &lt;a href=&#34;#bookmarking&#34;&gt;bookmarking section&lt;/a&gt;. However, by now, I use it heavily for almost all of my notes and other types of self-written content. I think Notion&amp;rsquo;s mix of markdown syntax support, slash commands, and WYSIWYG makes for a great writing experience.&lt;/p&gt;
&lt;p&gt;I strongly recommend organizing all your notes in a single database with appropriate tags, such as &lt;code&gt;meeting&lt;/code&gt;, &lt;code&gt;presentation&lt;/code&gt;, &lt;code&gt;tc&lt;/code&gt;, and &lt;code&gt;question&lt;/code&gt;. Similar to the bookmarks database described above, Notion will automatically provide a column with the creation time of the note. If you have frequent meetings with the same people, you can think about adding a &lt;em&gt;Participants&lt;/em&gt; column.&lt;/p&gt;
&lt;p&gt;A notes database is the perfect use case for another great Notion feature: &lt;a href=&#34;https://www.notion.so/Database-templates-454ed5ab5bd24226b58d176697bd7e10&#34;&gt;Templates&lt;/a&gt;. This feature will allow you to created templates for your different types of notes and then, for example, add a new meeting note with one click. Depending on the template, the new note comes with a pre-defined layout and might include fields for the meeting&amp;rsquo;s participants and agenda. This is what opens when I click to add new meeting notes in my database:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/notion-meeting-notes.png&#34;
         alt=&#34;My basic meeting notes template.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;My basic meeting notes template.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h1 id=&#34;project-specific-knowledge&#34;&gt;Project-specific Knowledge&lt;/h1&gt;
&lt;p&gt;In my experience, it is best to keep project information as closely together as possible. For me, this means that issue tracking, merge requests (i.e. pull requests), documentation, and everything else that comes with a software project should live alongside the source code.&lt;/p&gt;
&lt;p&gt;This practice guarantees that anyone who works on the code now, or in the future, has access to all the information. My solution for this is to use GitLab for everything related to a specific project. This includes pretty much everything except some quick notes that I sometimes write in Notion because I do not want anyone else to see them.&lt;/p&gt;
&lt;p&gt;To do this, GitLab offers a lot of project management and documentation features, such as issue management, a project wiki, a Code snippet space for all projects and accounts, and more.
A project wiki is a great place for all documentation that is not specific to an issue. This can include the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instructions for setting up the development environment&lt;/li&gt;
&lt;li&gt;Instructions for manual deployment&lt;/li&gt;
&lt;li&gt;Architecture descriptions and diagrams. I am a big fan of &lt;a href=&#34;https://mermaidjs.github.io/#/&#34;&gt;mermaid&lt;/a&gt;, which allows creating UML diagrams with Markdown and is supported by GitLab.&lt;/li&gt;
&lt;li&gt;Guidelines regarding naming conventions, design paradigms, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;If you have read my post on &lt;a href=&#34;https://tkainrad.dev/posts/using-hugo-gitlab-pages-and-cloudflare-to-create-and-run-this-website/&#34;&gt;running and hosting this website&lt;/a&gt;, you know that I use GitLab also for this personal blog project. Nevertheless, I use Notion for much of the project documentation and management tasks, because it comes with some unique benefits for this use case, as described &lt;a href=&#34;#blog-posts&#34;&gt;above&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;Of course, there are alternatives. GitHub has caught up in the past and offers a very similar feature set. I have only limited experience with Atlassian products, but I suppose you can achieve the same thing by using a mix of BitBucket, Confluence, and Jira.&lt;br&gt;
On a side note, writing in Confluence feels a lot like writing in Notion. Both recognize markdown syntax and offer slash commands to quickly insert complex content types.&lt;/p&gt;
&lt;h1 id=&#34;managing-files&#34;&gt;Managing Files&lt;/h1&gt;
&lt;p&gt;This one is relatively straightforward. I think the most important thing is to use some form of cloud storage. Personally, I use Dropbox.&lt;br&gt;
Next, you should think about a proper folder structure. Finally, you should be able to search for your files quickly.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&#34;https://tkainrad.dev/posts/setting-up-linux-workstation/&#34;&gt;Linux&lt;/a&gt; and rely on Albert for searching through files. If this doesn&amp;rsquo;t work I use &lt;a href=&#34;https://linuxize.com/post/locate-command-in-linux/&#34;&gt;the &lt;code&gt;locate&lt;/code&gt; command&lt;/a&gt; and, my last resort are command-line tools, such as &lt;code&gt;find&lt;/code&gt;, and &lt;code&gt;grep&lt;/code&gt;. They are still king for complex search requirements, such as regex matching and including also file content.&lt;/p&gt;
&lt;p&gt;If you can tick the three boxes&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;availability on all devices&lt;/li&gt;
&lt;li&gt;structure&lt;/li&gt;
&lt;li&gt;searchable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;you should be all set.&lt;/p&gt;

&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;Notion databases support file columns. This means you can upload a different file to each cell. I have not yet found a use case related directly to software engineering for this. However, it is great for managing invoices.&lt;/p&gt;

&lt;/div&gt;
&lt;h1 id=&#34;additional-use-cases&#34;&gt;Additional Use Cases&lt;/h1&gt;
&lt;p&gt;In this section, I want to present some special kinds of knowledge management use cases that are unique to software engineering. Most of them I have picked up properly only after starting to use &lt;a href=&#34;https://www.notion.so/?r=cb45b9cefd824015a044b3336009be32&#34;&gt;Notion&lt;/a&gt;. By no means, I want to say that you should copy all of them, but you are very welcome to try out what you think looks interesting.&lt;/p&gt;
&lt;h2 id=&#34;code-snippets&#34;&gt;Code Snippets&lt;/h2&gt;
&lt;p&gt;Currently, I have two ways of collecting code snippets. I hope I can eventually integrate them somehow.&lt;/p&gt;
&lt;h3 id=&#34;vscode-user-snippets&#34;&gt;VSCode User Snippets&lt;/h3&gt;
&lt;p&gt;The first one are &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;VSCode&lt;/a&gt; User Snippets. VSCode does many things right and snippet management is one of them. It is very easy to define new snippets and use them by typing a predefined string. Simply press &lt;code&gt;Ctrl&lt;/code&gt;-&lt;code&gt;Shift&lt;/code&gt;-&lt;code&gt;p&lt;/code&gt; and choose &lt;em&gt;Preferences: Configure User Snippets&lt;/em&gt;. Then, you can split your snippets into multiple files or just put all of them together in the &lt;code&gt;global-snipptes.code-snippets&lt;/code&gt; file. These are some of my snippets for writing blog posts with markdown and Hugo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;figure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;:&lt;/span&gt; {
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;markdown&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;prefix&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;fig&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: [
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;{{&amp;lt; figure src=\&amp;#34;/images/\&amp;#34;  class=\&amp;#34;center-figure\&amp;#34;  caption=\&amp;#34;\&amp;#34; &amp;gt;}}&amp;#34;&lt;/span&gt;
    ],
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;Insert hugo figure shortcode&amp;#34;&lt;/span&gt;
}&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;,&lt;/span&gt;
&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;callout&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;:&lt;/span&gt; {
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;markdown&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;prefix&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;callout&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: [
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;{{% callout \&amp;#34;warning info tip note\&amp;#34; %}}&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;{{%/callout %}}&amp;#34;&lt;/span&gt;
    ],
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;Insert hugo callout shortcode&amp;#34;&lt;/span&gt;
}&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;,&lt;/span&gt;
&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;:&lt;/span&gt; {
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;markdown&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;prefix&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: [
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;{{&amp;lt; highlight bash \&amp;#34;linenos=table\&amp;#34;&amp;gt;}}&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;{{&amp;lt; / highlight &amp;gt;}}&amp;#34;&lt;/span&gt;
    ],
    &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;Insert hugo code shortcode&amp;#34;&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The snippets can then be used by typing the prefix and pressing &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Space&lt;/code&gt;:
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/vscode-insert-snippet.gif&#34;/&gt; 
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&#34;notion-snippet-database&#34;&gt;Notion Snippet database&lt;/h3&gt;
&lt;p&gt;The second use case concerns small pieces of code that I have written myself and that I would like to remember. This is not necessarily for productivity reasons, but rather for nostalgia. It is ideal for small algorithms, for example when you manage to substantially increase the performance of something by applying some clever technique.&lt;/p&gt;
&lt;p&gt;I keep those snippets in a Notion database, which works great because I can tag them and add arbitrary properties. A nice benefit of this habit is that it&amp;rsquo;s not a problem if you don&amp;rsquo;t do it for a while. Your database will not look messy all of a sudden.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/notion-snippet.database.png&#34;
         alt=&#34;An exemplary entry of my code snippets database in Notion.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;An exemplary entry of my code snippets database in Notion.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;shortcut-database&#34;&gt;Shortcut Database&lt;/h2&gt;
&lt;p&gt;I believe that typing proficiency is important for a software engineer. It is easier to stay in flow if you can type fast and navigate around your IDE and tools with shortcuts. As my set of tools grew, I realized that I have a hard time to keep track of which shortcuts I am using, which of them work in which application, and whether I can change them so that they work across as many tools as possible.&lt;/p&gt;
&lt;p&gt;Therefore, I started to keep track of some shortcuts I would like to use everywhere. These are things like creating new tabs, creating new windows, opening the respective tool&amp;rsquo;s search feature and more.&lt;/p&gt;
&lt;p&gt;This database helps me identify overlaps and motivates me to think about which task could fit for a specific key-combination that I use often. For example, I use &lt;code&gt;Ctrl&lt;/code&gt; - &lt;code&gt;Shift&lt;/code&gt; - &lt;code&gt;T&lt;/code&gt; in IDEs to search for type definitions and  &lt;code&gt;Ctrl&lt;/code&gt; - &lt;code&gt;Shift&lt;/code&gt; - &lt;code&gt;R&lt;/code&gt; to search for resources in general. Since I have these key combinations memorized for years and can use it very quickly, I want to make use of it wherever possible. Therefore, I try to set up my applications so that some kind of search opens whenever I use one of these combinations. My Notion database makes it easy to see which applications offer search features and which of them I can modify.&lt;/p&gt;
&lt;p&gt;For example, my Browser now forwards &lt;code&gt;Ctrl&lt;/code&gt; - &lt;code&gt;Shift&lt;/code&gt; - &lt;code&gt;T&lt;/code&gt; / &lt;code&gt;R&lt;/code&gt; to &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;Workona&lt;/a&gt; and allows me to switch/search workspaces or use the general search, respectively.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/shortcuts-database.png&#34;
         alt=&#34;Screenshot of my Notion shortcut database&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Screenshot of my Notion shortcut database&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Notion&amp;rsquo;s filtering and search capabilities are great for identifying problems with your setup. For me, a problem is when two applications use different shortcuts for a very similar operation. Unfortunately, Notion is negative example of an application that doesn&amp;rsquo;t let you customize its shortcuts and therefore reduces the usefulness of my database. If someone from the Notion team reads this at some point, I kindly ask you to lobby on my behalf to prioritize personalized keyboard shortcuts.&lt;/p&gt;
&lt;p&gt;I am excited about this use case and will talk about it in much more detail in a future blog post.&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;As of June 3rd, 2020, there is still no dedicated blog post for this. However, there is something more valuable:&lt;br&gt;
This post gave me the idea for &lt;a href=&#34;https://keycombiner.com&#34;&gt;https://keycombiner.com&lt;/a&gt;.&lt;br&gt;
It is a web application to track the keyboard shortcuts you use, get better at using them, and to learn new ones.
It is in open beta and I would love to hear your feedback!&lt;/p&gt;

&lt;/div&gt;
&lt;h2 id=&#34;tools-database&#34;&gt;Tools Database&lt;/h2&gt;
&lt;p&gt;I also have a Notion database to keep track of small web tools that I use. This serves little purpose for things that are used frequently as you will remember them anyway. However, for minor things that are only needed once in a while, such as color palette generators, detecting handwriting as LaTeX symbols, and checking SSL certificates this is quite handy. Usually, you can find these tools via google, but sometimes there are many tools for a task and it is nice to keep track of the ones that work best.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/managing-my-personal-knowledge-base/tools-database.png&#34;
         alt=&#34;Screenshot of my software tools database in Notion.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Screenshot of my software tools database in Notion.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Again, the important thing here is to not overdo it. There are extensive publicly available lists of such tools. Your list should not be a copy of those but rather a small collection of the things you like and need from time to time.&lt;/p&gt;
&lt;h2 id=&#34;collecting-ideas-for-new-projects&#34;&gt;Collecting Ideas for new Projects&lt;/h2&gt;
&lt;p&gt;Like many software engineers in these golden times, I sometimes think about starting new software projects, maybe even bootstrapping a small business.&lt;br&gt;
You probably guessed it already, I keep ideas for possible projects in a Notion database. The main benefit is, once again, that it allows me to easily link it with other databases, such as my bookmarks.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Similar posts often conclude with warnings that you should be very careful not to spend too much time on organizing and maintaining your knowledge and workflows. In principle, I agree with this sentiment. After all, you want to &lt;em&gt;increase&lt;/em&gt; your productivity.&lt;/p&gt;
&lt;p&gt;I do believe, however, that it is worth it to spend some time thinking about your knowledge management &lt;em&gt;system&lt;/em&gt;. The most important part about conceptualizing a system is to decide exactly which types of information you want to maintain in your knowledge base. If you get this right you will benefit for the rest of your career. Even if the tools might change in the future, the system will stay.&lt;/p&gt;
&lt;p&gt;Please don&amp;rsquo;t hesitate to share your own experiences in the comments below. I am sure that my workflows are not perfect, but they might get closer with your tips.&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;This post is released together with &lt;a href=&#34;https://tkainrad.dev/posts/reading-list-organizing-knowledge/&#34;&gt;a new post in my &lt;em&gt;Reading List&lt;/em&gt; series&lt;/a&gt;, which lists related resources. If you want to dive even deeper into knowledge management concepts, you might want to have a look.&lt;/p&gt;

&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Copy-paste ready commands to set up SGE, PBS/TORQUE, or SLURM clusters</title>
      <link>https://tkainrad.dev/posts/copy-paste-ready-instructions-to-set-up-1-node-clusters/</link>
      <pubDate>Fri, 18 Oct 2019 00:00:00 +0000</pubDate>
      
      <guid>https://tkainrad.dev/posts/copy-paste-ready-instructions-to-set-up-1-node-clusters/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Local HPC clusters continue to play a vital role in scientific research. Many universities, research institutions, and companies continue to maintain on-site clusters despite the efforts of the big cloud providers to expand their offerings into this area.&lt;/p&gt;
&lt;p&gt;The software systems responsible for making these clusters of computers work together can be called &lt;em&gt;Distributed Research Management System.&lt;/em&gt; The most commonly used ones are SGE, PBS/TORQUE, and SLURM. Unfortunately, setting those up can be very painful. There is a lot of outdated information on the internet. It is required to fight with several different configuration files and minor issues can mean that no command will run properly.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/drms.svg&#34;
         alt=&#34;Operating principle of a traditional resource-manager based computing cluster.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Operating principle of a traditional resource-manager based computing cluster.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;If your task is to set up a large system that will be used for many years and you have got several days to do this perfectly, this might not be a problem. However, if you just want to play around with the different systems, spending several hours until you can submit your first job is a very bleak outlook.&lt;/p&gt;
&lt;p&gt;Therefore, I present copy-paste-ready instructions for setting up SGE, PBS/TORQUE, or SLURM on a single machine, which will act as the master and a compute node at the same time. All guides are tested on Ubuntu 18.04, but should work with little modification on most recent Linux installations. These commands can also serve to create container images or other automated setup workflows.&lt;/p&gt;
&lt;p&gt;Naturally, caution is warranted when executing commands as a super user. If you apply the listed commands on a production system, please make sure you understand everything that is done.&lt;/p&gt;
&lt;h1 id=&#34;slurm&#34;&gt;Slurm&lt;/h1&gt;
&lt;p&gt;Trying to set up SLURM on my development machine in order to run some test suites that need to interface with SLURM cost me quite a bit of time. There are plenty of extensive tutorials available. In contrast to SGE and PBS, there is even an up-to-date &lt;a href=&#34;https://slurm.schedmd.com/quickstart_admin.html&#34;&gt;official documentation&lt;/a&gt;. However, those resources cover much more than is needed for a single-node cluster and it is easy to get lost in the many configuration options that you will not need at first.&lt;/p&gt;
&lt;p&gt;Fortunately, I found &lt;a href=&#34;https://ubuntuforums.org/showthread.php?t=2404746&#34;&gt;this thread&lt;/a&gt; in the Ubuntu forums, which is the basis for my SLURM instructions.&lt;/p&gt;
&lt;p&gt;Start by installing munge and slurm:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sudo apt install munge slurm-wlm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, create a new file at &lt;code&gt;/etc/slurm-llnl/slurm.conf&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-PacmanConf&#34; data-lang=&#34;PacmanConf&#34;&gt;&lt;span style=&#34;color:#309&#34;&gt;ControlMachine&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&amp;lt;YOUR-HOST-NAME&amp;gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;MpiDefault&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;none&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;ProctrackType&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;proctrack/pgid&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;ReturnToService&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;1&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SlurmctldPidFile&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/var/run/slurm-llnl/slurmctld.pid&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SlurmdPidFile&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/var/run/slurm-llnl/slurmd.pid&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SlurmdSpoolDir&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/var/lib/slurm-llnl/slurmd&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SlurmUser&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;slurm&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;StateSaveLocation&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/var/lib/slurm-llnl/slurmctld&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SwitchType&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;switch/none&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;TaskPlugin&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;task/none&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# SCHEDULING&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;FastSchedule&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;1&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SchedulerType&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;sched/builtin&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SelectType&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;select/linear&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# LOGGING AND ACCOUNTING&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;AccountingStorageType&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;accounting_storage/none&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;ClusterName&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&amp;lt;YOUR-HOST-NAME&amp;gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;JobAcctGatherType&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;jobacct_gather/none&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SlurmctldLogFile&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/var/log/slurm-llnl/slurmctld.log&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;SlurmdLogFile&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/var/log/slurm-llnl/slurmd.log&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# COMPUTE NODES&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;NodeName&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&amp;lt;YOUR-HOST-NAME&amp;gt; &lt;span style=&#34;color:#309&#34;&gt;CPUs&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;4 &lt;span style=&#34;color:#309&#34;&gt;Sockets&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;1 &lt;span style=&#34;color:#309&#34;&gt;CoresPerSocket&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;4 &lt;span style=&#34;color:#309&#34;&gt;ThreadsPerCore&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;2 &lt;span style=&#34;color:#309&#34;&gt;State&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;UNKNOWN&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#309&#34;&gt;PartitionName&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;long &lt;span style=&#34;color:#309&#34;&gt;Nodes&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&amp;lt;YOUR-HOST-NAME&amp;gt; &lt;span style=&#34;color:#309&#34;&gt;Default&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;YES &lt;span style=&#34;color:#309&#34;&gt;MaxTime&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;INFINITE &lt;span style=&#34;color:#309&#34;&gt;State&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;UP&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You only need to replace &lt;code&gt;&amp;lt;YOUR-HOST-NAME&amp;gt;&lt;/code&gt; with your actual hostname. Simply execute the &lt;code&gt;hostname&lt;/code&gt; command if you are not sure what it is. Of course, you can also modify other settings, such as the number of CPUs, but the basic configuration from above should be enough for our 1-node cluster.&lt;/p&gt;
&lt;p&gt;We are almost finished, just enable and start the manager slurmctld:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sudo systemctl &lt;span style=&#34;color:#366&#34;&gt;enable&lt;/span&gt; slurmctld
sudo systemctl start slurmctld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, enable and start the agent &lt;code&gt;slurmd&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sudo systemctl &lt;span style=&#34;color:#366&#34;&gt;enable&lt;/span&gt; slurmd
sudo systemctl start slurmd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Congratulations, your Slurm system should be up an running! Use &lt;code&gt;sinfo&lt;/code&gt; to check the status of the manager and the agent. The command &lt;code&gt;scontrol show node&lt;/code&gt; will give you information about your node setup.&lt;/p&gt;
&lt;p&gt;If Slurm did not start, fear not, there is likely only a small fix required. Start by looking for an error message with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;systemctl status slurmd.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Does it say that the &lt;code&gt;slurmd.pid&lt;/code&gt; file coud not be opened? If so, your &lt;code&gt;slurm.conf&lt;/code&gt; file probably has different values for &lt;code&gt;SlurmctldPidFile&lt;/code&gt; and &lt;code&gt;SlurmdPidFile&lt;/code&gt; than your &lt;code&gt;slurmctld.service&lt;/code&gt; file. Check by printing the latter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;less /usr/lib/systemd/system/slurmctld.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It might show &lt;code&gt;PIDFile=/run/slurmctld.pid&lt;/code&gt;, which means that we need to change &lt;code&gt;SlurmctldPidFile&lt;/code&gt; and &lt;code&gt;SlurmdPidFile&lt;/code&gt; in our &lt;code&gt;/etc/slurm-llnl/slurm.conf&lt;/code&gt; to the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;SlurmctldPidFile&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/run/slurmctld.pid
&lt;span style=&#34;color:#033&#34;&gt;SlurmdPidFile&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/run/slurmd.pid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that, try again to start &lt;code&gt;slurmctld&lt;/code&gt; and &lt;code&gt;slurmd&lt;/code&gt; with the above commands.&lt;/p&gt;
&lt;h1 id=&#34;sge&#34;&gt;SGE&lt;/h1&gt;
&lt;p&gt;This one is not so simple.&lt;/p&gt;
&lt;p&gt;Some parts of the following setup are taken from a public &lt;a href=&#34;https://github.com/robsyme/docker-sge/blob/master/Dockerfile&#34;&gt;Dockerfile&lt;/a&gt; created by &lt;a href=&#34;https://github.com/robsyme&#34;&gt;Robert Syme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, gain root permissions. On Ubuntu you can type &lt;code&gt;sudo -i&lt;/code&gt;. All commands have to be executed with root permissions.&lt;/p&gt;
&lt;p&gt;Then, create a new folder, let&amp;rsquo;s say via &lt;code&gt;mkdir /opt/sge/installfolder&lt;/code&gt;. Set the new folder&amp;rsquo;s location as an environment variable in the current shell via&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;INSTALLFOLDER&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/opt/sge/installfolder.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, execute the following commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;$INSTALLFOLDER&lt;/span&gt;
wget https://arc.liv.ac.uk/downloads/SGE/releases/8.1.9/sge-common_8.1.9_all.deb .
wget https://arc.liv.ac.uk/downloads/SGE/releases/8.1.9/sge-doc_8.1.9_all.deb .
wget https://arc.liv.ac.uk/downloads/SGE/releases/8.1.9/sge_8.1.9_amd64.deb .
dpkg -i ./*.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, download the following 4 files and place them also into the created folder, in our case into &lt;code&gt;/opt/sge/installfolder&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://tkainrad.dev/other/sge_init.sh&#34; download&gt;sge_init.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tkainrad.dev/other/sge_auto_install.conf&#34; download&gt;sge_auto_install.conf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tkainrad.dev/other/sge_hostgrp.conf&#34; download&gt;sge_hostgrp.conf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tkainrad.dev/other/sge_exec_host.conf&#34; download&gt;sge_exec_host.conf&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Most of the magic will happen through those scripts and configuration files. After the download, we need to set some environment variables in the current shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;SGE_ROOT&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;/opt/sge
&lt;span style=&#34;color:#366&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;SGE_CELL&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We also need to set a new &lt;code&gt;profile.d&lt;/code&gt; config via&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;ln -s &lt;span style=&#34;color:#033&#34;&gt;$SGE_ROOT&lt;/span&gt;/&lt;span style=&#34;color:#033&#34;&gt;$SGE_CELL&lt;/span&gt;/common/settings.sh /etc/profile.d/sge_settings.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, execute the following to install SGE and perform setup operations:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;cd&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;$SGE_ROOT&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./inst_sge -m -x -s -auto &lt;span style=&#34;color:#033&#34;&gt;$INSTALLFOLDER&lt;/span&gt;/sge_auto_install.conf &lt;span style=&#34;color:#c30;font-weight:bold&#34;&gt;\\&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sleep &lt;span style=&#34;color:#f60&#34;&gt;10&lt;/span&gt; &lt;span style=&#34;color:#c30;font-weight:bold&#34;&gt;\\&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; /etc/init.d/sgemaster.sge-cluster restart &lt;span style=&#34;color:#c30;font-weight:bold&#34;&gt;\\&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; /etc/init.d/sgeexecd.sge-cluster restart &lt;span style=&#34;color:#c30;font-weight:bold&#34;&gt;\\&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sed -i &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;s/HOSTNAME/`hostname`/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;$INSTALLFOLDER&lt;/span&gt;/sge_exec_host.conf &lt;span style=&#34;color:#c30;font-weight:bold&#34;&gt;\\&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sed -i &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;s/HOSTNAME/`hostname`/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#033&#34;&gt;$INSTALLFOLDER&lt;/span&gt;/sge_hostgrp.conf &lt;span style=&#34;color:#c30;font-weight:bold&#34;&gt;\\&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; /opt/sge/bin/lx-amd64/qconf -Me &lt;span style=&#34;color:#033&#34;&gt;$INSTALLFOLDER&lt;/span&gt;/sge_exec_host.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, our new cluster is already up and running. However, we still need to add users to the &lt;code&gt;sgeusers&lt;/code&gt; group, which was defined in the &lt;code&gt;sge_hostgrp.conf&lt;/code&gt; file you  just applied. Only users from this group are allowed to submit jobs. Therefore, we run the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;/opt/sge/bin/lx-amd64/qconf -au &amp;lt;USER&amp;gt; sgeusers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, run &lt;code&gt;$INSTALLFOLDER/sge_init.sh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can now delete the complete &lt;code&gt;$INSTALLFOLDER&lt;/code&gt;, or at least run&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;rm &lt;span style=&#34;color:#033&#34;&gt;$INSTALLFOLDER&lt;/span&gt;/*.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After a restart to load the new &lt;code&gt;profile.d&lt;/code&gt; settings, all users that were added to &lt;code&gt;sgeusers&lt;/code&gt; should be able to submit jobs. Test this via:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;echo Running test from &lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$HOSTNAME&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt; | qsub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;pbs--torque&#34;&gt;PBS / Torque&lt;/h1&gt;
&lt;p&gt;This is a little simpler again. Most of the setup is taken from &lt;a href=&#34;https://jabriffa.wordpress.com/2015/02/11/installing-torquepbs-job-scheduler-on-ubuntu-14-04-lts/&#34;&gt;another blog&lt;/a&gt;. Some inspiration is also from a public Dockerfile available at &lt;a href=&#34;https://hub.docker.com/r/agaveapi/torque/&#34;&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, gain root permissions. On Ubuntu you can type &lt;code&gt;sudo -i&lt;/code&gt;. All commands have to be executed with root permissions.&lt;/p&gt;
&lt;p&gt;We start by installing the relevant packages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;apt-get install torque-server torque-client torque-mom torque-pam
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Installing these packages will create a default setup. Unfortunately, this is complex and would require complex changes to get to a working cluster. Instead, we stop all torque services and create a clean setup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;/etc/init.d/torque-mom stop
/etc/init.d/torque-scheduler stop
/etc/init.d/torque-server stop
pbs_server -t create
killall pbs_server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We start by setting &lt;code&gt;localhost&lt;/code&gt; as the server host and allowing root to change the database configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; localhost &amp;gt; /etc/torque/server_name
&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; localhost &amp;gt; /var/spool/torque/server_priv/acl_svr/acl_hosts
&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; root@localhost &amp;gt; /var/spool/torque/server_priv/acl_svr/operators
&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; root@localhost &amp;gt; /var/spool/torque/server_priv/acl_svr/managers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the following commands, we set &lt;code&gt;localhost&lt;/code&gt; also as compute node with 4 cores available:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;SERVER.DOMAIN np=4&amp;#34;&lt;/span&gt; &amp;gt; /var/spool/torque/server_priv/nodes
&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; localhost &amp;gt; /var/spool/torque/mom_priv/config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can already start the daemon processes again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;/etc/init.d/torque-server start
/etc/init.d/torque-scheduler start
/etc/init.d/torque-mom start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After this &lt;code&gt;qmgr&lt;/code&gt; is ready to start the scheduler:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set server scheduling = true&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set server keep_completed = 300&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set server mom_job_sync = true&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following commands are to create a default queue and to configure it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;create queue batch&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set queue batch queue_type = execution&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set queue batch started = true&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set queue batch enabled = true&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set queue batch resources_default.walltime = 3:00:00&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set queue batch resources_default.nodes = 1&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set server default_queue = batch&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, we allow our machine to submit to the new cluster:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set server submit_hosts = &amp;lt;hostname&amp;gt;&amp;#39;&lt;/span&gt;
qmgr -c &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;set server allow_node_submit = true&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To test the setup, you can use the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;echo Running test from &lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$HOSTNAME&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt; | qsub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The target audience for this post is probably very small. I decided to do it anyway, as there might be someone that can benefit immensely. Personally, I would have saved a lot of time if I found such a blog post a year ago. Also, I might need it again myself at some point.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Setting up a Linux Workstation for Software Development</title>
      <link>https://tkainrad.dev/posts/setting-up-linux-workstation/</link>
      <pubDate>Tue, 13 Aug 2019 00:00:00 +0000</pubDate>
      
      <guid>https://tkainrad.dev/posts/setting-up-linux-workstation/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In my opinion, Linux is the best operating system for a software engineer, except they develop explicitly for Windows or macOS. Whenever I read about new features for the &lt;a href=&#34;https://docs.microsoft.com/en-us/windows/wsl/about&#34;&gt;Windows Subsystem for Linux&lt;/a&gt;, I wonder why people settle for anything less than the real thing. Linux aids many of my workflows with its customizability, superior command-line experience, native support for containerization platforms, a dependable package management system, and many other features that I will describe in this blog post. macOS comes close, but, in my opinion, falls short due to exorbitant hardware costs and less room for customization.&lt;/p&gt;
&lt;p&gt;Still, as with any other operating system, optimizing a Linux workstation for software development requires some configuration. In this post, I will present tools and concepts that I think are very helpful, but overlooked by many. I will try to show only things that are not specific to my workflows, but rather useful for almost any software engineer, DevOps specialist, or just regular productivity enthusiast. Naturally, many of the configuration options and tools covered in this post are subjective. Nevertheless, I am confident that my suggestions are a good place to start. They have served me well over the years and I continually try to optimize my setup. Hence, I very much appreciate any improvement you might suggest.&lt;/p&gt;
&lt;h1 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;A Linux machine&lt;/strong&gt;&lt;br&gt;
For this guide, I will use Ubuntu 20.04, which is the current LTS release. I am very happy with Ubuntu. Anything I don&amp;rsquo;t like can easily be changed. The biggest advantage over many other distributions is probably that the Ubuntu community is very large and it is usually easy to find people with similar problems. There is also a very active &lt;a href=&#34;https://askubuntu.com/&#34;&gt;StackExchange community&lt;/a&gt;.  However, most of the things covered in this post will apply to pretty much any Linux distribution and even macOS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some command-line experience&lt;/strong&gt;&lt;br&gt;
Much of this post is intended for people who feel right at home when they see a &lt;code&gt;~&lt;/code&gt;- character. If you are not comfortable working with command-lines and have no intention to change this, you can still read the other sections though.&lt;/p&gt;
&lt;h1 id=&#34;tweaking-ubuntu&#34;&gt;Tweaking Ubuntu&lt;/h1&gt;
&lt;p&gt;Before we start any serious work, I will point out some changes to Ubuntu itself that I apply on all my machines.&lt;/p&gt;
&lt;h2 id=&#34;appearance&#34;&gt;Appearance&lt;/h2&gt;
&lt;p&gt;One of the first things I do after installing Ubuntu is to install the &lt;em&gt;GNOME Tweak Tool&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo apt-get install gnome-tweak-tool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It enables complex modifications of the GNOME desktop environment. I recommend you play around with some of its options. For this guide, we will only consider the &lt;em&gt;Appearance&lt;/em&gt; section. Specifically, we want to change the default Ubuntu theme to another one that provides better contrasts and an overall cleaner experience, namely the &lt;a href=&#34;https://github.com/adapta-project/adapta-gtk-theme&#34;&gt;Adapta-gtk-theme&lt;/a&gt;, which is based on the Material Design guidelines.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo apt-get install adapta-gtk-theme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After installing the theme, you should restart the &lt;em&gt;GNOME Tweak Tool&lt;/em&gt;, and you can then select &lt;em&gt;Adapta-Eta&lt;/em&gt; as your new theme. The theme comes with some nice benefits that you wouldn&amp;rsquo;t think of at first. For example, it fixes the ridiculously small toolbar icons in the Eclipse IDE.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/adapta-elements.png&#34;
         alt=&#34;Adapta Theme elements (Source).&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Adapta Theme elements (&lt;a href=&#34;https://github.com/adapta-project/adapta-gtk-theme&#34;&gt;Source&lt;/a&gt;).&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;


&lt;div class=&#34;notices warning&#34;&gt;
    &lt;p&gt;Unfortunately, the Adapta theme is no longer actively maintained. It is still a perfectly fine theme to use and if you notice any glitches, you can always switch themes with a couple clicks. A possible alternative is &lt;a href=&#34;https://github.com/nana-4/materia-theme&#34;&gt;Materia&lt;/a&gt;, which also works well with the remainder of this blog post.&lt;/p&gt;

&lt;/div&gt;
&lt;h2 id=&#34;nautilus-type-ahead-search&#34;&gt;Nautilus Type-Ahead Search&lt;/h2&gt;
&lt;p&gt;The next thing I suggest is to change the Nautilus search behavior. With recent Ubuntu distributions, there is no type-ahead search in the standard file explorer. This means you can not start to type some letters and jump between files that start with these letters. Instead, Nautilus will enter a dedicated search mode that is confusing and quite slow for folders with a large number of files.&lt;/p&gt;
&lt;p&gt;Fortunately, we can easily get the old behavior back:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo add-apt-repository ppa:lubomir-brindza/nautilus-typeahead
sudo apt dist-upgrade
killall nautilus &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# to force a restart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/type-ahead-search.gif&#34;
         alt=&#34;Searching through my /bin folder by typing ahead (Source).&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Searching through my &lt;code&gt;/bin&lt;/code&gt; folder by typing ahead (&lt;a href=&#34;https://github.com/adapta-project/adapta-gtk-theme&#34;&gt;Source&lt;/a&gt;).&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;There is a &lt;a href=&#34;https://askubuntu.com/a/278553/188679&#34;&gt;StackExchange answer&lt;/a&gt; that provides further details.&lt;/p&gt;
&lt;h2 id=&#34;hibernation&#34;&gt;Hibernation&lt;/h2&gt;
&lt;p&gt;Another thing that is essential for me is hibernation. Usually, I will only shutdown my computer once a week or even less. However, I am not a big fan of suspending for long periods of time. Power outages could have unforeseen consequences and I simply feel a little better if my machines are off the grid altogether.&lt;/p&gt;
&lt;p&gt;Unfortunately, setting up hibernation is tricky and can depend on your hardware. I updated this section multiple times already to contain the most robust solution, but you never quite know.
If you don&amp;rsquo;t care about hibernation, you should probably skip this section and spare yourself the trouble.&lt;/p&gt;
&lt;p&gt;In principle, hibernation is possible out of the box. Just type &lt;code&gt;sudo systemctl hibernate&lt;/code&gt;. However, this is likely to fail with an error. My fix for this relies on a mixture of &lt;a href=&#34;https://linuxize.com/post/how-to-add-swap-space-on-ubuntu-20-04/#creating-a-swap-file&#34;&gt;this&lt;/a&gt; and &lt;a href=&#34;https://rephlex.de/blog/2019/12/27/how-to-hibernate-and-resume-from-swap-file-in-ubuntu-20-04-using-full-disk-encryption/&#34;&gt;that&lt;/a&gt; blog post. First, we need to find out the current size of our swap file:&lt;/p&gt;

&lt;div class=&#34;notices warning&#34;&gt;
    &lt;p&gt;The below instructions assume that you use Ubuntu 20.04 with a swap file. This is the default for new installations. However, if you upgraded from a previous version, you might still have a swap partition. In this case, the process is similar, but not covered here.&lt;/p&gt;

&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo swapon --show &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# or `cat /proc/swaps`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If this is less than your main memory (RAM), you will need to increase it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo swapoff -a
sudo fallocate -l &amp;lt;SIZE&amp;gt;G /swapfile
sudo chmod &lt;span style=&#34;color:#f60&#34;&gt;600&lt;/span&gt; /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo swapon --show &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# to verify changed size&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we need to find out the UUID and offset of our now large enough swapfile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;sudo swap-offset /swapfile
&amp;gt; &amp;lt;OFFSET&amp;gt;
sudo findmnt -no SOURCE,UUID -T /swapfile 
&amp;gt; &amp;lt;UUID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this, we are almost done. Using the UUID and the file offset, we edit the following line in &lt;code&gt;/etc/default/grub&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#c30&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;quiet splash resume=UUID=&amp;lt;UUID&amp;gt; resume_offset=&amp;lt;OFFSET&amp;gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, we create a &lt;code&gt;conf.d&lt;/code&gt; resume file. Simply do &lt;code&gt;sudo nano /etc/initramfs-tools/conf.d/resume&lt;/code&gt; and add the content &lt;code&gt;RESUME=UUID=&amp;lt;UUID&amp;gt;&lt;/code&gt; to the file. At last, we need to update grup and initramfs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo update-grub
sudo update-initramfs -u -k all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, you should be able to do &lt;code&gt;sudo systemctl hibernate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Please let me know if this approach doesn&amp;rsquo;t work on your system. I would like to include potential problems in this post, if there are any.&lt;/p&gt;
&lt;h1 id=&#34;boosting-command-line-productivity&#34;&gt;Boosting Command-Line Productivity&lt;/h1&gt;
&lt;p&gt;I believe that command-line proficiency can significantly boost developer productivity. This is especially true in times of DevOps and NoOps, where developers are supposed to handle deployment pipelines and cloud infrastructure. Fortunately, there are some tools that can help you become a command-line wizard.&lt;/p&gt;
&lt;h2 id=&#34;shortcuts&#34;&gt;Shortcuts&lt;/h2&gt;
&lt;p&gt;Before going forward, I would suggest to set up some general terminal shortcuts. Simply go to &lt;em&gt;Edit -&amp;gt; Preferences -&amp;gt; Shortcuts&lt;/em&gt;. I like to replicate web browser shortcuts for opening new tabs and windows, closing tabs, and cycling between tabs.&lt;/p&gt;

&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;Did you know that all common terminal emulators have an Undo shortcuts with &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;-&lt;/kbd&gt;?
Among many other things, my side-project &lt;a href=&#34;https://keycombiner.com&#34;&gt;KeyCombiner&lt;/a&gt; has a public &lt;a href=&#34;https://keycombiner.com/collecting/collections/public/136&#34;&gt;collection of terminal shortcuts&lt;/a&gt;, many of which are barely known and still very useful.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;However, using this interface, it is not possible to set up &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Tab&lt;/kbd&gt; and &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;Tab&lt;/kbd&gt; as tab switching shortcuts. Gnome has some issues with using the &lt;kbd&gt;Tab&lt;/kbd&gt; key in shortcut configurations. Thanks to &lt;a href=&#34;https://askubuntu.com/a/875482/188679&#34;&gt;this answer from the Ubuntu community&lt;/a&gt;, we can get around this. Simply execute the following in your terminal:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;gsettings &lt;span style=&#34;color:#366&#34;&gt;set&lt;/span&gt; org.gnome.Terminal.Legacy.Keybindings:/org/gnome/terminal/legacy/keybindings/ next-tab &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;&amp;lt;Primary&amp;gt;Tab&amp;#39;&lt;/span&gt;
gsettings &lt;span style=&#34;color:#366&#34;&gt;set&lt;/span&gt; org.gnome.Terminal.Legacy.Keybindings:/org/gnome/terminal/legacy/keybindings/ prev-tab &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;&amp;lt;Primary&amp;gt;&amp;lt;Shift&amp;gt;Tab&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;switching-from-bash-to-zsh&#34;&gt;Switching from Bash to Zsh&lt;/h2&gt;
&lt;p&gt;A couple of months ago, I made an important change in my life. I switched from Bash to Zsh.&lt;/p&gt;
&lt;p&gt;There are a lot of blog posts, threads, and articles that compare Bash and Zsh, e.g.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.howtogeek.com/362409/what-is-zsh-and-why-should-you-use-it-instead-of-Bash/&#34;&gt;What is ZSH, and Why Should You Use It Instead of Bash?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackabuse.com/zsh-vs-bash/&#34;&gt;Zsh vs Bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/wearetheledger/oh-my-zsh-made-for-cli-lovers-installation-guide-3131ca5491fb&#34;&gt;Oh-My-Zsh! A Work of CLI Magic — Tutorial for Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the end it boils down to one thing: &lt;strong&gt;Plugin and theme support&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Zsh has an amazing themes and plugins ecosystem. Theme support allows you to easily get a beautiful shell. Plugins range from simple auto-completion for all kinds of applications and tools(git, mvn, hugo, &amp;hellip;) to complex stuff like improved search capabilities. Because of this fact alone, Zsh is superior to Bash.&lt;/p&gt;
&lt;p&gt;However, chances are that you grew fond of Bash and that you get a bad feeling when somebody tells you that there is something better. I understand, it was the same for me. Still, I urge you to give it a shot. The transition is very painless since pretty much everything you like about Bash still works with Zsh. You will not have to learn new commands.&lt;/p&gt;
&lt;h3 id=&#34;installing-zsh&#34;&gt;Installing Zsh&lt;/h3&gt;
&lt;p&gt;Installing Zsh on Ubuntu is very easy. We can use the regular package manager:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo apt install zsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, we set Zsh as our new default shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;chsh -s &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;$(&lt;/span&gt;which zsh&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;The &lt;code&gt;chsh&lt;/code&gt; command updates the &lt;code&gt;/etc/passwd&lt;/code&gt; file, but does not affect the current session. You need to log out and log in again to have zsh as your default shell.&lt;/p&gt;

&lt;/div&gt;
&lt;h3 id=&#34;configuring-zsh-history&#34;&gt;Configuring Zsh History&lt;/h3&gt;
&lt;p&gt;For me there are few things worse than searching for an old shell command only to find out that the shell&amp;rsquo;s history size was set to a ridiculously low default number and that, because of this, the command was not saved.&lt;/p&gt;
&lt;p&gt;Therefore, we extend the Zsh history size by putting this at the end of the &lt;code&gt;~/.zshrc&lt;/code&gt; configuration file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;HISTSIZE&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f60&#34;&gt;10000000&lt;/span&gt;
&lt;span style=&#34;color:#033&#34;&gt;SAVEHIST&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f60&#34;&gt;10000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For me, the command history is a tool to search for previous commands I might need now. I do not use it as a protocol for what I did when and in which exact order. Therefore, I use the following options to get rid of all duplicates in my history automatically:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;## History command configuration&lt;/span&gt;
    
setopt HIST_IGNORE_ALL_DUPS &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# ignore duplicated commands history list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also, I like to use multiple terminal sessions in parallel, potentially working on the same problem. For this, it helps a lot to share the same history among all sessions. It can be accomplished by&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;setopt SHARE_HISTORY &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# share command history data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you are transitioning from Bash to Zsh, you probably want to keep your existing Bash history. In contrast to Bash, Zsh stores timestamps in its history file. Therefore, re-using the Bash history file does not work out of the box. Fortunately, all we need to do is to append some timestamp to all the commands from our previous Bash history and put them into the new Zsh history file. You could easily script this yourself or use one of the many good scripts that other people wrote, &lt;a href=&#34;https://gist.github.com/goyalankit/a1c88bfc69107f93cda1&#34;&gt;such as this one&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;zsh-features-that-are-not-in-bash&#34;&gt;Zsh Features that are not in Bash&lt;/h3&gt;
&lt;p&gt;Once we have Zsh installed and finished our basic history configuration, we can start to take a look at some out-of-the-box features that make it stand out in comparison with Bash. If these do not impress you, keep in mind that the real big thing is plugin support, which I cover &lt;a href=&#34;#installing-zsh-plugins&#34;&gt;below&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;recursive-path-expansion&#34;&gt;Recursive Path Expansion&lt;/h4&gt;
&lt;p&gt;Zsh can do much more sophisticated expansions than Bash. This is documented in detail in &lt;a href=&#34;http://zsh.sourceforge.net/Doc/Release/Expansion.html&#34;&gt;the Zsh manual&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One feature that you can easily start to use is recursive path expansion. If you type &lt;code&gt;cd /usr/local/b&lt;/code&gt; in Bash, you can then press &lt;code&gt;Tab&lt;/code&gt; to expand this to &lt;code&gt;cd /usr/local/bin&lt;/code&gt;. With Zsh, you can also type &lt;code&gt;cd /u/lo/b&lt;/code&gt; and then press &lt;code&gt;Tab&lt;/code&gt;. Zsh will recursively expand all path elements:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/recursive-path-expansion.gif&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The above animation shows also that you can omit &lt;code&gt;cd&lt;/code&gt; when changing directories.&lt;/p&gt;
&lt;h4 id=&#34;calculator-zcalc&#34;&gt;Calculator: zcalc&lt;/h4&gt;
&lt;p&gt;Before switching to Zsh, I was often using the Python Shell as a calculator. However, this has a few downsides. Obviously, the Python Shell is not primarily developed to be a good calculator app. For example,  simple operations, such as &lt;code&gt;sqrt&lt;/code&gt;, require import statements, and there are no convenient ways to access results of previous lines.&lt;/p&gt;
&lt;p&gt;The calculator script shipped with Zsh is a very simple and efficient solution. Before using it, it has to be loaded:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;autoload -Uz zcalc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you plan to use it often, you can add the &lt;code&gt;autoload&lt;/code&gt; command to your &lt;code&gt;~/.zshrc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, start the calculator with &lt;code&gt;zcalc&lt;/code&gt; and do some calculations:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/zcalc.gif&#34;
         alt=&#34;Results of previous operations can be accessed with the $-character.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Results of previous operations can be accessed with the &lt;code&gt;$&lt;/code&gt;-character.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&#34;advanced-aliasing&#34;&gt;Advanced Aliasing&lt;/h4&gt;
&lt;p&gt;Zsh has some unique aliasing capabilities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Suffix Aliases&lt;/strong&gt;&lt;br&gt;
This means you can assign applications to file suffixes, e.g. &lt;code&gt;alias -s txt=vscode&lt;/code&gt; will allow you to open a &lt;code&gt;.txt&lt;/code&gt; file with Visual Studio Code by just typing &lt;code&gt;file.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Global Aliases&lt;/strong&gt;&lt;br&gt;
Global aliases are set with the &lt;code&gt;-g&lt;/code&gt; flag and allow to specify a replacement for any part of a command. For example, if you set &lt;code&gt;alias -g G=&#39; | grep&#39; &lt;/code&gt; you will be able to do the following:
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/global-alias.gif&#34;/&gt; 
&lt;/figure&gt;
&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;To make aliases permanent, it is required to add them to your &lt;code&gt;~/.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;h3 id=&#34;installing-zsh-plugins&#34;&gt;Installing ZSH plugins&lt;/h3&gt;
&lt;p&gt;Finally, it is time to explore the real strength of Zsh, which means installing plugins to boost our productivity above anything this anime character has ever seen before:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/vegeta.gif&#34;/&gt; 
&lt;/figure&gt;

&lt;h4 id=&#34;package-manager-oh-my-zsh&#34;&gt;Package Manager: Oh my Zsh&lt;/h4&gt;
&lt;p&gt;A good place to start is to install &lt;a href=&#34;https://github.com/robbyrussell/oh-my-zsh&#34;&gt;Oh my Zsh&lt;/a&gt;, &amp;ldquo;a community-driven framework for managing your Zsh configuration.&amp;rdquo; Simply do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Copy the template configuration file &lt;code&gt;.zshrc.zsh-template&lt;/code&gt; in the .&lt;code&gt;zshrc&lt;/code&gt; home directory and apply the configuration by executing the source command. Both can be done at once by executing the following line:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Oh my Zsh&lt;/em&gt; comes with many themes and plugins that we only have to enable in the configuration file in order to use them. In the next section, we will start by selecting a pretty theme.&lt;/p&gt;
&lt;h4 id=&#34;theme-agnoster&#34;&gt;Theme: Agnoster&lt;/h4&gt;
&lt;p&gt;Personally, I like the &lt;em&gt;agnoster&lt;/em&gt; theme. It works well with the Adapta-Eta Gnome theme we have set &lt;a href=&#34;#appearance&#34;&gt;previously&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To enable a theme, set ZSH_THEME to the name of the theme in your &lt;code&gt;~/.zshrc&lt;/code&gt;, in my case this is  &lt;code&gt;ZSH_THEME=agnoster&lt;/code&gt;. If you have troubles with special characters not being shown properly, install the Powerline font package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo apt-get install fonts-powerline
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;Oh my Zsh&lt;/em&gt; GitHub wiki provides a &lt;a href=&#34;https://github.com/robbyrussell/oh-my-zsh/wiki/Themes&#34;&gt;well curated list of available themes along with screenshots&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All pictures and animations of terminals you see in this post show the Agnoster theme with slight modifications to the prompt. In particular, I removed the git-part of the prompt and added a newline part instead. If you would like to replicate this, edit your  &lt;code&gt;~/.oh-my-zsh/themes/agnoster.zsh-theme&lt;/code&gt; and replace the &lt;code&gt;## Main prompt&lt;/code&gt; part close to the end with the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;prompt_newline&lt;span style=&#34;color:#555&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;[[&lt;/span&gt; -n &lt;span style=&#34;color:#033&#34;&gt;$CURRENT_BG&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;then&lt;/span&gt;
    &lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; -n &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34; %{%k%F{&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$CURRENT_BG&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;}%}&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$SEGMENT_SEPARATOR&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;%{%k%F{&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$CURRENT_BG&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;}%}&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$SEGMENT_SEPARATOR&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;else&lt;/span&gt;
    &lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; -n &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34; %{%k%}&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;fi&lt;/span&gt;

  &lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; -n &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34; %{%f%}&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#033&#34;&gt;CURRENT_BG&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;}&lt;/span&gt;

&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;## Main prompt&lt;/span&gt;
build_prompt&lt;span style=&#34;color:#555&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#033&#34;&gt;RETVAL&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$?&lt;/span&gt;
  prompt_status
  prompt_virtualenv
  prompt_aws
  prompt_context
  prompt_dir
  prompt_bzr
  prompt_hg
  prompt_newline
  prompt_end
&lt;span style=&#34;color:#555&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Additionally, I recommend changing the font color of the directory part of the prompt from black to white. In my opinion, this provides better contrast with the dark blue background:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# Dir: current working directory&lt;/span&gt;
prompt_dir&lt;span style=&#34;color:#555&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;{&lt;/span&gt;
  prompt_segment blue white &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;%~&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;basic-plugins&#34;&gt;Basic Plugins&lt;/h4&gt;
&lt;p&gt;Next, you should enable some included plugins via adding them to your &lt;code&gt;plugins&lt;/code&gt; setting in your &lt;code&gt;~/.zshrc&lt;/code&gt; file. After this step, it might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;plugins&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=(&lt;/span&gt;colored-man-pages git python django mvn aws docker vscode&lt;span style=&#34;color:#555&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can browse all the plugins that come with &lt;em&gt;Oh my Zsh&lt;/em&gt; in the official &lt;a href=&#34;https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins&#34;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The above listed plugins are rather trivial, they provide command completion and define a set of aliases and shortcuts that come in handy when working with the respective tool. Nevertheless, this provides a real productivity boost. For example, finding out which git commands start with &lt;code&gt;r&lt;/code&gt; becomes much simpler:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/git-r.gif&#34;/&gt; 
&lt;/figure&gt;

&lt;h4 id=&#34;jump-to-frequently-used-directories&#34;&gt;Jump to Frequently Used Directories&lt;/h4&gt;
&lt;p&gt;Most command-line work happens in just a handful of directories. For me, these are primarily the root folders of various software development projects. Of course, I could manually set aliases for these folders so that I can quickly switch between them, but this would be tedious.&lt;/p&gt;
&lt;p&gt;Fortunately, there is a better solution with &lt;a href=&#34;https://github.com/rupa/z&#34;&gt;z&lt;/a&gt;. It tracks your most used directories and will take you to them via &lt;code&gt;z &amp;lt;query&amp;gt;&lt;/code&gt;. The &lt;code&gt;query&lt;/code&gt; can be any part of target directory&amp;rsquo;s path:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/gifs/z.gif&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The software is already bundled with &lt;em&gt;Oh my Zsh&lt;/em&gt;, simply add z to the list of plugins:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;plugins&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=(&lt;/span&gt;z colored-man-pages git python django mvn aws docker vscode&lt;span style=&#34;color:#555&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I could have probably included this one in the list of basic plugins above, but I wanted to highlight it because I find it particularly useful.&lt;/p&gt;
&lt;h4 id=&#34;supercharging-history-search&#34;&gt;Supercharging History Search&lt;/h4&gt;
&lt;p&gt;The original Bash history search always bothered me. Repeatedly pressing &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; and hoping to get lucky at some point is very cumbersome if you have lots of similar commands containing the query. To be fair, there are also great additions for Bash that improve this situation, such as &lt;a href=&#34;https://github.com/cantino/mcfly&#34;&gt;McFly&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, this is about improving history search with Zsh. I believe the best solution is using &lt;a href=&#34;https://github.com/jimeh/zsh-peco-history&#34;&gt;peco-history&lt;/a&gt;. It is a Zsh plugin that relies on &lt;a href=&#34;https://github.com/peco/peco&#34;&gt;peco&lt;/a&gt; to interactively filter through your history file. Peco is a general-purpose interactive filtering tool that you can (and should!) also use as a stand-alone tool in your terminal. On Ubuntu, we can install it from the official repositories:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo apt-get install peco
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards clone &lt;a href=&#34;https://github.com/jimeh/zsh-peco-history&#34;&gt;zsh-peco-history&lt;/a&gt; into the &lt;code&gt;$ZSH_CUSTOM/plugins&lt;/code&gt; directory. Zsh will automatically resolve the pre-set shell variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;git clone https://github.com/jimeh/zsh-peco-history.git &lt;span style=&#34;color:#033&#34;&gt;$ZSH_CUSTOM&lt;/span&gt;/plugins/zsh-peco-history
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, add &lt;code&gt;zsh-peco-history&lt;/code&gt; to the list of plugins:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;plugins&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=(&lt;/span&gt;zsh-peco-history z colored-man-pages git python django mvn aws docker vscode&lt;span style=&#34;color:#555&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The plugin will be ready once you start a new terminal session.&lt;/p&gt;
&lt;p&gt;The following animation shows that this improved history search was very helpful for writing this blog post. It allowed me to easily search for the exact commands I used when I set up my current machine:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/gifs/peco-search.gif&#34;
         alt=&#34;Searching shell history with peco.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Searching shell history with &lt;a href=&#34;https://github.com/peco/peco&#34;&gt;peco&lt;/a&gt;.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&#34;autosuggestions&#34;&gt;Autosuggestions&lt;/h4&gt;
&lt;p&gt;Our new history search is great. The bad news is that we will not use it very often, because there is something that is even better in most cases: &lt;a href=&#34;https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md&#34;&gt;zsh-autosuggestions&lt;/a&gt;&lt;br&gt;
This plugin suggests completions for your commands as you type. By default, the suggested completion will be the first match in your history. This is how it looks like:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/gifs/autosuggestions.gif&#34;
         alt=&#34;Using a suggested git command-line.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Using a suggested &lt;code&gt;git&lt;/code&gt; command-line.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span style=&#34;color:#a00&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;:-&lt;/span&gt;~/.oh-my-zsh/custom&lt;span style=&#34;color:#a00&#34;&gt;}&lt;/span&gt;/plugins/zsh-autosuggestions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterward, add &lt;code&gt;zsh-autosuggestions&lt;/code&gt; to your plugins setting in your &lt;code&gt;~/.zshrc&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;plugins&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=(&lt;/span&gt;zsh-autosuggestions zsh-peco-history z colored-man-pages git python django mvn aws docker vscode&lt;span style=&#34;color:#555&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;syntax-highlighting&#34;&gt;Syntax Highlighting&lt;/h4&gt;
&lt;p&gt;Another great plugin is &lt;a href=&#34;https://github.com/zsh-users/zsh-syntax-highlighting&#34;&gt;zsh-syntax-highlighting&lt;/a&gt;. It highlights commands while you are typing them. This is especially useful for catching syntax errors. Once again, install via git:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;git clone https://github.com/zsh-users/zsh-syntax-highlighting.git &lt;span style=&#34;color:#a00&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;:-&lt;/span&gt;~/.oh-my-zsh/custom&lt;span style=&#34;color:#a00&#34;&gt;}&lt;/span&gt;/plugins/zsh-syntax-highlighting
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, add &lt;code&gt;zsh-syntax-highlighting&lt;/code&gt; to your plugins setting in your &lt;code&gt;~/.zshrc&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#033&#34;&gt;plugins&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=(&lt;/span&gt;zsh-syntax-highlighting zsh-autosuggestions zsh-peco-history z colored-man-pages git python django mvn aws docker vscode&lt;span style=&#34;color:#555&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/syntax-highlighting.gif&#34;
         alt=&#34;Syntax highlighting also indicates whether a command is typed correctly.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Syntax highlighting also indicates whether a command is typed correctly.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&#34;clipboard-tool&#34;&gt;Clipboard Tool&lt;/h4&gt;
&lt;p&gt;This one is not really a full-blown plugin. &lt;em&gt;Oh my Zsh&lt;/em&gt; comes with a script called &lt;code&gt;clipcopy&lt;/code&gt; out of the box. It is a simple tool that enables clipboard copy and past operations from the command-line:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&amp;lt;command&amp;gt; | clipcopy    &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# copies stdin to clipboard&lt;/span&gt;
clipcopy &amp;lt;file&amp;gt;         &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# copies the content of a file to clipboard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If this doesn&amp;rsquo;t work, you are probably missing &lt;code&gt;xclip&lt;/code&gt;. Install it via&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo apt-get install xclip 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Somehow, I have a hard time remembering the name &lt;em&gt;clipcopy&lt;/em&gt;, therefore I set a global alias as &lt;a href=&#34;https://tkainrad.dev/posts/setting-up-linux-workstation/#advanced-aliasing&#34;&gt;described above&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#366&#34;&gt;alias&lt;/span&gt; -g &lt;span style=&#34;color:#033&#34;&gt;ctrlc&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#39; | clipcopy&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#366&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;copythisinclipboard&amp;#34;&lt;/span&gt; ctrlc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;If you don&amp;rsquo;t use &lt;em&gt;Oh my Zsh&lt;/em&gt;, you can get the functionality of &lt;em&gt;clipcopy&lt;/em&gt; via &lt;a href=&#34;https://github.com/twang817/zsh-clipboard&#34;&gt;an actual plugin&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;h1 id=&#34;ssh-setup&#34;&gt;SSH Setup&lt;/h1&gt;
&lt;p&gt;One of the great advantages of using Linux instead of Windows is the out-of-the-box SSH support. Immediately after installing your distribution, you can start to access remote servers.&lt;/p&gt;
&lt;p&gt;However, there is some room for streamlining your SSH tasks. You can avoid lots of repetitive typing if you modify your &lt;code&gt;.ssh/config&lt;/code&gt; file and setup meaningful defaults for the machines you access regularly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;Host ec2-instance &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# you can freely chose a name here that will act as alias for this host&lt;/span&gt;
    HostName &amp;lt;ip-address or hostname&amp;gt;
    User tkainrad


Host cluster &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# you can freely chose a name here that will act as alias for this host&lt;/span&gt;
    HostName &amp;lt;ip-address or hostname&amp;gt;
    User tkainrad
    IdentityFile &lt;span style=&#34;color:#c30&#34;&gt;`&lt;/span&gt;/home/tkainrad/cluster_rsa.pub&lt;span style=&#34;color:#c30&#34;&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For more sophisticated settings, look up the &lt;a href=&#34;https://linux.die.net/man/5/ssh_config&#34;&gt;&lt;code&gt;ssh_config&lt;/code&gt; man page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to go one step further, you can set up public key authentication so you can login to your most-used remote hosts without having to re-enter your password each time.
With &lt;a href=&#34;https://www.ssh.com/ssh/copy-id&#34;&gt;&lt;code&gt;ssh-copy-id&lt;/code&gt;&lt;/a&gt;, there is a simple tool that streamlines this process. If you have your hosts already configured via the &lt;code&gt;.ssh/config&lt;/code&gt; file, just do&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;ssh-copy-id ec2-instance
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By default, &lt;code&gt;ssh-copy-id&lt;/code&gt; will take your public key in &lt;code&gt;~.ssh/id_rsa.pub&lt;/code&gt;. If you want to use different keys for each of your remote hosts, check out the &lt;a href=&#34;http://manpages.ubuntu.com/manpages/trusty/man1/ssh-copy-id.1.html&#34;&gt;man page&lt;/a&gt; page or &lt;a href=&#34;https://www.howtogeek.com/tips/bypass-ssh-logins-by-adding-your-key-to-a-remote-server-in-a-single-command/&#34;&gt;this more extensive guide&lt;/a&gt;. If you use keys other than &lt;code&gt;~.ssh/id_rsa.pub&lt;/code&gt; you also have to add an &lt;code&gt;IdentityFile&lt;/code&gt; entry to your &lt;code&gt;.ssh/config&lt;/code&gt; settings. Afterwards, you will be able to access the machine by simply doing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;ssh ec2-instance
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;additional-tools&#34;&gt;Additional Tools&lt;/h1&gt;
&lt;p&gt;A great terminal gets you a long way. However, some additional tools can help make your workstation more complete. In this section, I try to present some of my favorites that could be useful to almost anyone.&lt;/p&gt;
&lt;h2 id=&#34;text-editing-vscodehttpscodevisualstudiocom&#34;&gt;Text Editing: &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;VSCode&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For most of my more extensive software engineering projects, I use JetBrains products or Eclipse. I will not describe setting up those in this post, as this would easily mandate a separate article. However, I present a more lightweight editing environment that is often a better choice than to start up a full-blown IDE. For a software engineer, especially for one that deals also with DevOps workloads, it is the daily business to edit and view all kinds of text-based files, such as .&lt;code&gt;txt&lt;/code&gt;, &lt;code&gt;.csv&lt;/code&gt;, &lt;code&gt;.md&lt;/code&gt;, &lt;code&gt;xml&lt;/code&gt;, &lt;code&gt;.yml&lt;/code&gt;, and &lt;code&gt;.json&lt;/code&gt;. For this, it is essential to have a fast text editor which can deal with large files and still provides sophisticated editing features.&lt;/p&gt;
&lt;p&gt;Previously, I used Sublime. For a couple of months now, I have switched to Visual Studio Code and I am still amazed by it. Comparing it to Sublime makes little sense in my opinion, because VSCode is just on a whole other level. Even for software projects with relatively simple technology stacks, such as this blog website, I now prefer VSCode over Eclipse or the JetBrains suite.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/vscode.png&#34;
         alt=&#34;Screenshot of VSCode showing the default light theme (Light&amp;#43;) (Source).&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Screenshot of VSCode showing the default light theme (Light+) (&lt;a href=&#34;https://superdevresources.com/best-vscode-light-themes/&#34;&gt;Source&lt;/a&gt;).&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The easiest way to install Visual Studio Code on Ubuntu is to visit the &lt;a href=&#34;https://code.visualstudio.com/&#34;&gt;official website&lt;/a&gt; and to download the Debian package. You could have probably figured out how to do this yourself, but do you also know how to set VSCode as the default application for all text files? Simply do&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;xdg-mime default code.desktop text/plain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will spare you the headache of doing &lt;em&gt;Right-Click -&amp;gt; Properties -&amp;gt; Open With -&amp;gt; Set as default&lt;/em&gt; on every file type separately.&lt;/p&gt;
&lt;p&gt;Switching to VSCode from Sublime (or any other editor) is a surprisingly pleasant experience. VSCode will recommend the most relevant plugins as you go. For example, if you open a &lt;code&gt;.py&lt;/code&gt; file, some extensions for Python development will be recommended. Installing them is then just a click away and doesn&amp;rsquo;t even require a restart of the application. After some days of following VSCode&amp;rsquo;s recommendations and occasionally searching for some extensions manually, my setup was more complete and efficient than it ever was with Sublime.&lt;/p&gt;
&lt;h3 id=&#34;vscode-terminal-with-agnoster&#34;&gt;VSCode Terminal with Agnoster&lt;/h3&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;If you don&amp;rsquo;t intend to use the integrated VSCode terminal, you can safely skip this section.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;If you followed this guide until here and you now open an integrated Terminal in VSCode, you will likely be a bit disappointed. There are several problems. With our current setup, we need a monospace font, and the coloring does not work nicely with VSCode&amp;rsquo;s light theme.&lt;/p&gt;
&lt;p&gt;Fortunately, we can fix these things:&lt;/p&gt;
&lt;p&gt;First, install the &lt;a href=&#34;https://github.com/abertsch/Menlo-for-Powerline&#34;&gt;Menlo for Powerline&lt;/a&gt; font:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;git clone https://github.com/abertsch/Menlo-for-Powerline.git
sudo mv &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;Menlo for Powerline.ttf&amp;#34;&lt;/span&gt; /usr/share/fonts/
sudo fc-cache -vf /usr/share/fonts/ &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# Refresh fonts cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, we change our terminal prompt colors a little bit to be compatible with both light and dark themes. Open &lt;code&gt;~/.oh-my-zsh/themes/agnoster.zsh-theme&lt;/code&gt; and change &lt;code&gt;prompt_context&lt;/code&gt; to the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;# Context: user@hostname (who am I and where am I)&lt;/span&gt;
prompt_context&lt;span style=&#34;color:#555&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$USER&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt; !&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$DEFAULT_USER&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;||&lt;/span&gt; -n &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#033&#34;&gt;$SSH_CLIENT&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#555&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;then&lt;/span&gt;
    prompt_segment cyan default &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;%(!.%{%F{yellow}%}.)%n@%m&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;fi&lt;/span&gt;
&lt;span style=&#34;color:#555&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, we apply the new font and the new colors in the VSCode settings. Press &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;P&lt;/kbd&gt; and start to type &lt;code&gt;Preferences: Open Settings (JSON)&lt;/code&gt;. We can now add the following lines to &lt;code&gt;settings.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;    &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;terminal.integrated.fontFamily&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;Menlo for Powerline&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;,&lt;/span&gt; 
    &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;workbench.colorCustomizations&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;:&lt;/span&gt; {
        &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;terminal.ansiBlue&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;#01A0E4&amp;#34;&lt;/span&gt;,
        &lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;&amp;#34;terminal.ansiCyan&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;#B5E4F4&amp;#34;&lt;/span&gt;,
    }&lt;span style=&#34;color:#a00;background-color:#faa&#34;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The integrated VSCode terminal now looks nice and has all the functionality of all of our Zsh plugins.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/vscode-terminal.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;sync-configuration-files-mackuphttpsgithubcomlramackup&#34;&gt;Sync Configuration Files: &lt;a href=&#34;https://github.com/lra/mackup&#34;&gt;Mackup&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So you just set up your desktop workstation, modified a bunch of configuration files, manually adjusted your VSCode keyboard shortcuts and now you want to do this also with your notebook?&lt;/p&gt;
&lt;p&gt;The solution to this is one of my favorite tools of all: &lt;a href=&#34;https://github.com/lra/mackup&#34;&gt;Mackup&lt;/a&gt;&lt;br&gt;
It will use any software that can sync a folder, such as Dropbox, to keep your application settings in sync.&lt;/p&gt;
&lt;p&gt;You can install it with &lt;code&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;pip install --upgrade mackup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;If you have versioning troubles with &lt;code&gt;pip&lt;/code&gt; or Python on Ubuntu 20.04, I recommend to do &lt;code&gt;sudo apt install python-is-python3&lt;/code&gt;. It will symlink &lt;code&gt;/usr/bin/python&lt;/code&gt; to &lt;code&gt;python3&lt;/code&gt; and hence make your transition to a world without Python 2 easier.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;Once Mackup is installed, you can copy your application settings to Dropbox (per default) doing&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;mackup backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To apply them at a different machine, just use&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;mackup restore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Behind the scenes, Mackup copies your configuration files to your Dropbox and then replaces the originals with symbolic links. Have a look at the &lt;a href=&#34;https://github.com/lra/mackup#bullsht-what-does-it-really-do-to-my-files&#34;&gt;GitHub Readme&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h2 id=&#34;advanced-screenshots-shutterhttpslaunchpadnetshutter&#34;&gt;Advanced Screenshots: &lt;a href=&#34;https://launchpad.net/shutter&#34;&gt;Shutter&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are coming from Windows, you probably use the Snipping Tool on a regular basis. With &lt;em&gt;Screenshot&lt;/em&gt;, Ubuntu has a similar tool installed by default. However, there is another option that is superior to both the Windows Snipping Tool and the Ubuntu default: &lt;a href=&#34;https://launchpad.net/shutter&#34;&gt;Shutter&lt;/a&gt;&lt;br&gt;
Unfortunately, it is no longer included in the default package repositories since Ubuntu 18.10. So, we have to add a third-party PPA first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo add-apt-repository ppa:linuxuprising/shutter
sudo apt-get install shutter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is very simple to use and does not force you to become familiar with its advanced features. There are a few alternatives that are still actively developed, such as &lt;a href=&#34;https://github.com/flameshot-org/flameshot&#34;&gt;Flameshot&lt;/a&gt;. Unfortunately, those are missing a lot of Shutter&amp;rsquo;s more advanced features. So, I will stick with Shutter for as long as I can make it run on Ubuntu.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/shutter.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;pick-colors-pickhttpswwwkryogenixorgcodepick&#34;&gt;Pick Colors: &lt;a href=&#34;https://www.kryogenix.org/code/pick/&#34;&gt;Pick&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you do front-end development, chances are you need a color picking tool on your computer. The most commonly used tool on Ubuntu is GPick. However, it drives me crazy. Usually, I just want to pick a color and get the hex code into my clipboard. GPick makes this very hard. So instead, I recommend &lt;a href=&#34;https://www.kryogenix.org/code/pick/&#34;&gt;Pick&lt;/a&gt;, a simple and functional alternative.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/pick.png&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;cheatsheet-keycombiner-desktophttpskeycombinercomdesktop&#34;&gt;Cheatsheet: &lt;a href=&#34;https://keycombiner.com/desktop/&#34;&gt;KeyCombiner Desktop&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most people know KeyCombiner as a tool for browsing and learning shortcuts. However, its desktop app serves an additioanl purpose with its instant lookup feature: It is a context-aware cheatsheet that can show the shortcuts of the currently active application in addition to whatever key combinations and text snippets I have in my personal KeyCombiner collections.&lt;/p&gt;
&lt;p&gt;To trigger it, I only have to press &lt;kbd&gt;Super&lt;/kbd&gt;+&lt;kbd&gt;Alt&lt;/kbd&gt;+&lt;kbd&gt;C&lt;/kbd&gt;. The main advantage is that I don&amp;rsquo;t have to leave the current context and can resume work right after looking up the required piece of information:&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/keycombiner/lookup-three-apps2.gif&#34;
         alt=&#34;KeyCombiner&amp;amp;rsquo;s instant shortcut lookup for VSCode, Terminal, and Chrome.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;KeyCombiner&amp;rsquo;s instant shortcut lookup for VSCode, Terminal, and Chrome.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;communication-hub-ferdihttpsgetferdicom&#34;&gt;Communication Hub: &lt;a href=&#34;https://getferdi.com/&#34;&gt;Ferdi&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Did you ever see someone using their phone while sitting in front of their personal computer? Chances are, they were using a communication app that they could have used much more efficiently from their larger device with an actual keyboard. To get the benefit of receiving all notifications from all my communication tools, and to be able to respond easily, I use &lt;a href=&#34;https://getferdi.com/&#34;&gt;Ferdi&lt;/a&gt;. It is particularly useful if you have to monitor several Slack teams.&lt;/p&gt;
&lt;p&gt;In contrast to most of its competitors (Rambox, Wavebox, Franz 5), Ferdi is completely free and open-source.&lt;/p&gt;

&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;If you want Ferdi or any other software that is distributed via an AppImage to show up properly in the dock, have a look at &lt;a href=&#34;https://github.com/AppImage/appimaged&#34;&gt;appimaged&lt;/a&gt;. It is open-source software that monitors specific directories for AppImage files and installs them properly in the system.&lt;/p&gt;

&lt;/div&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;Previous versions of this article recommended &lt;a href=&#34;https://getstation.com/&#34;&gt;Station&lt;/a&gt; instead of Ferdi. However, Station pivoted to become a browser extension and is no longer an option for bundling communication channels outside of your regular browser.&lt;/p&gt;

&lt;/div&gt;
&lt;h2 id=&#34;record-short-screencasts-peekhttpsgithubcomphwpeek&#34;&gt;Record Short Screencasts: &lt;a href=&#34;https://github.com/phw/peek&#34;&gt;Peek&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Did you wonder how I created those fancy gifs showing my terminal? I thought so.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/phw/peek&#34;&gt;Peek&lt;/a&gt; is a very lightweight and simple tool to record short screencasts. To install it on Ubuntu do&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;sudo add-apt-repository ppa:peek-developers/stable
sudo apt update
sudo apt install peek
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://tkainrad.dev/images/5/peek-recording-itself.gif&#34;
         alt=&#34;Peek in action. (Source).&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Peek in action. (&lt;a href=&#34;https://github.com/phw/peek&#34;&gt;Source&lt;/a&gt;).&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;During the creation of this article, I was made aware by a &lt;a href=&#34;https://knasmueller.net/&#34;&gt;good friend and fellow software engineer&lt;/a&gt; of dedicated terminal recording tools, such as &lt;a href=&#34;https://terminalizer.com/&#34;&gt;Terminalizer&lt;/a&gt; and &lt;a href=&#34;https://asciinema.org/&#34;&gt;asciinema&lt;/a&gt;. However, these require some initial setup work, especially if you want to show off a theme and require that your animated terminal looks exactly like your actual terminal.&lt;br&gt;
Since I already recorded most of the animations, I decided to stay with Peek for this post. Nevertheless, if your use case is terminal recording, you should probably go with one of the linked projects instead of Peek.&lt;/p&gt;
&lt;h2 id=&#34;mail-client-thunderbirdhttpswwwthunderbirdneten-us&#34;&gt;Mail Client: &lt;a href=&#34;https://www.thunderbird.net/en-US/&#34;&gt;Thunderbird&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For mail, I use &lt;a href=&#34;https://www.thunderbird.net/en-US/&#34;&gt;Thunderbird&lt;/a&gt;. I don&amp;rsquo;t particularly like it, but to my knowledge it is still the best desktop email client for Linux. Unfortunately, some minor design decisions make the program almost unusable for me in its default state. The reason I include this section about software that everyone knows already is mainly to highlight three changes I always make to the default setup:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;By default, Thunderbird sorts messages by date ascending. I think that&amp;rsquo;s an unfortunate default. Who wants to scroll down constantly to see the newest messages? To change the sort order to descending (newest first), go to &lt;em&gt;Preferences -&amp;gt; General -&amp;gt; Config Editor&lt;/em&gt; and set &lt;em&gt;mailnews.default_sort_order&lt;/em&gt; to value 2. See &lt;a href=&#34;https://superuser.com/a/13551/573438&#34;&gt;this StackExchange answer&lt;/a&gt; for more details about default sorting orders and other options.&lt;/li&gt;
&lt;li&gt;Install the &lt;a href=&#34;https://addons.thunderbird.net/en-US/thunderbird/addon/no-message-pane-sort-by-mouse/&#34;&gt;No Message Pane Sort by Mouse&lt;/a&gt; add-on.
With this extension, a click on the mail list table header will no longer change the defined sort order. Without it, misclicks while trying to select the first mail in the list are very annoying. Personally, I never want to change the sort order at all. However, it is still possible by holding &lt;kbd&gt;Ctrl&lt;/kbd&gt; while clicking.&lt;/li&gt;
&lt;li&gt;Finally, go to &lt;em&gt;Preferences -&amp;gt; Composition&lt;/em&gt; and uncheck the &lt;em&gt;Use Paragraph format instead of Body Text by default&lt;/em&gt; to prevent Thunderbird       from adding absurd amounts of whitespace whenever you press the Enter key while composing a mail.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;Are you already using Thunderbird on another computer? Fortunately, there is an easy way to migrate all your mail accounts and settings. Essentially, you can copy a hidden folder where Thunderbird stores all its data and move it to the new machine, &lt;a href=&#34;https://support.mozilla.org/en-US/kb/moving-thunderbird-data-to-a-new-computer&#34;&gt;as described in Mozilla&amp;rsquo;s official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;If you know of a new fancy alternative to Thunderbird that handles parallel usage of several mail accounts well, please let me know.&lt;/p&gt;
&lt;h1 id=&#34;bonus-tip&#34;&gt;Bonus Tip&lt;/h1&gt;
&lt;p&gt;If you have read this far, I am willing to share my most secret Linux hack with you. Joking aside, it is very helpful to know what to do when your Linux workstation freezes. For some reason, I did not know until a couple years ago. Maybe the following trick can help you to avoid some forced restarts in the future.&lt;/p&gt;
&lt;p&gt;The most flexible way to re-gain control of a system that has frozen completely is pressing &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Alt&lt;/kbd&gt;+&lt;kbd&gt;F3&lt;/kbd&gt;. Then, use top and other process monitoring tools to find the process IDs of the faulty processes. Then, simply kill them (e.g. type &lt;code&gt;kill &amp;lt;pid&amp;gt;&lt;/code&gt;, &lt;code&gt;killall&lt;/code&gt;, or &lt;code&gt;kill -9&lt;/code&gt;). Afterward, you can get back to your work using &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Alt&lt;/kbd&gt;+&lt;kbd&gt;F1&lt;/kbd&gt;. (&lt;a href=&#34;https://askubuntu.com/questions/547290/how-do-i-get-out-of-ctrl-alt-f3&#34;&gt;Source&lt;/a&gt;).&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I hope this post showed you some tools or practices that you didn&amp;rsquo;t know yet. I have had a good experience with all of them. Especially switching from Bash to Zsh and installing &lt;a href=&#34;http://localhost:1313/posts/setting-up-linux-machine/#installing-zsh-plugins&#34;&gt;the described plugins&lt;/a&gt; came with a real productivity boost. If you feel that I left out something important, I&amp;rsquo;d be very interested to hear your suggestions.&lt;/p&gt;
&lt;p&gt;If you are not mainly using Linux yet, the length of this post might give the impression that it is still a pain to set up a proper Linux workstation. However, you do not necessarily need all of the things I showed here. Also, everything covered in this post is very easy to install with minimal configuration overhead. I strongly believe that you would have a much harder time setting up a comparable Windows development workstation.&lt;/p&gt;
&lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://imgs.xkcd.com/comics/cautionary.png&#34;
         alt=&#34;You can still spend your life setting up Linux. However, if you use a popular, well-supported distribution you definitely don&amp;amp;rsquo;t have to. (Source: xkcd.com)&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;You can still spend your life setting up Linux. However, if you use a popular, well-supported distribution you definitely don&amp;rsquo;t have to. (Source: xkcd.com)&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

</description>
    </item>
    
  </channel>
</rss>