<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://www.linuxdeveloper.space/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.linuxdeveloper.space/" rel="alternate" type="text/html" /><updated>2024-03-07T14:03:57+00:00</updated><id>https://www.linuxdeveloper.space/feed.xml</id><title type="html">Linux Dev Space</title><subtitle>A free colloborative space for Linux developers to share their tuts and tips on Linux and Open Source.
</subtitle><author><name>Gayan Weerakutti</name></author><entry><title type="html">Connecting to WireGuard VPN Tunnel</title><link href="https://www.linuxdeveloper.space/configure-wireguard-client/" rel="alternate" type="text/html" title="Connecting to WireGuard VPN Tunnel" /><published>2022-04-01T18:30:00+00:00</published><updated>2022-04-01T18:30:00+00:00</updated><id>https://www.linuxdeveloper.space/configure-wireguard-client</id><content type="html" xml:base="https://www.linuxdeveloper.space/configure-wireguard-client/">&lt;p&gt;This guide provides the minimal first-step instructions required to connect to any WireGuard based VPN server.
If you also want to set up your own WireGuard server, you may start by reading the official &lt;a href=&quot;https://www.wireguard.com/quickstart/&quot;&gt;quickstart&lt;/a&gt; guide.&lt;/p&gt;

&lt;p&gt;I’ll be using a free-to-use, WireGuard based VPN service, SecurityKiss. 
They provide a limited free plan and affordable paid plans. No email registration is required to use it. The same steps should apply to other WireGuard based VPN servers as well.&lt;/p&gt;

&lt;p&gt;Start by downloading a VPN client configuration file from &lt;a href=&quot;https://securitykiss.com/download.html&quot;&gt;securitykiss.com/download&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The downloaded file would contain the following details.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Interface]
Address=&amp;lt;interface-ip&amp;gt;
PrivateKey=&amp;lt;client-private-key&amp;gt;
DNS=8.8.8.8

[Peer]
PublicKey=&amp;lt;server-public-key&amp;gt;
Endpoint=&amp;lt;server-public-ip&amp;gt;:7668
AllowedIPs=0.0.0.0/0,::/0
PersistentKeepalive=25
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SecurityKiss would generate all the placeholder values including the private key. 
So you don’t have to make any modifications to the downloaded config file to be able to use it.&lt;/p&gt;

&lt;p&gt;Then install the WireGuard client. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wireguard&lt;/code&gt; meta package include command line tools required to connect to WireGuard VPN servers.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install wireguard resolvconf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolvconf&lt;/code&gt; is internally used by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wireguard&lt;/code&gt; to set the interface’s DNS servers specified in the configuration file.&lt;/p&gt;

&lt;p&gt;Copy or move the config file to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/wireguard/&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo cp US_New_York_1.conf /etc/wireguard/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then to connect to the VPN tunnel:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo systemctl enable wg-quick@US_New_York_1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;US_New_York_1&lt;/code&gt; with the name of your configuration file.&lt;/p&gt;

&lt;p&gt;This will brings up a new network interface with properties supplied in the given configuration file.
The name of the network interface would be as same as the name of the configuration file.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl enable&lt;/code&gt; is used to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wg-quick.service&lt;/code&gt; start at boot.&lt;/p&gt;

&lt;p&gt;To find the details about the newly added network interface, run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ip address show
ip address show US_New_York_1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Gayan Weerakutti</name></author><category term="vpn" /><category term="security" /><summary type="html">This guide provides the minimal first-step instructions required to connect to any WireGuard based VPN server. If you also want to set up your own WireGuard server, you may start by reading the official quickstart guide.</summary></entry><entry><title type="html">Error Handling &amp;amp; Retry with Apache Beam and Flink</title><link href="https://www.linuxdeveloper.space/retry-apache-beam-flink/" rel="alternate" type="text/html" title="Error Handling &amp;amp; Retry with Apache Beam and Flink" /><published>2022-03-26T18:30:00+00:00</published><updated>2022-03-26T18:30:00+00:00</updated><id>https://www.linuxdeveloper.space/retry-apache-beam-flink</id><content type="html" xml:base="https://www.linuxdeveloper.space/retry-apache-beam-flink/">&lt;p&gt;This guide discusses one of the approaches to retry errors when running Apache Beam applications with Apache Flink. While the approach discussed here could be applied to any Beam pipeline in general, decide and settle on an error handling strategy that suits your use case.&lt;/p&gt;

&lt;p&gt;Apache Beam pipeline may throw exceptions while processing data. Some of these errors are transient (e.g., temporary difficulty accessing an external service), but some are permanent, such as errors caused by corrupt or unparseable input data.&lt;/p&gt;

&lt;h3 id=&quot;error-types&quot;&gt;Error Types&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Non-Transient Errors (Permanent)&lt;/li&gt;
  &lt;li&gt;Transient Errors (Temporary)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The diagram below illustrates a sample pipeline that reads data from an input stream, does some transformations, and writes data back to a data sink. Transient errors are handled using a checkpoint-based restart strategy, while a dead letter queue approach is used to handle non-transient errors.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/apache-beam/overall-retry-strategy.png&quot; alt=&quot;Retry strategies: dead letter queue approach, pipeline restart&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Since a non-transient error will continue to occur as long as it is not corrected, there’s no point in retrying such errors. Beam’s DoFn instances process elements in arbitrary bundles. If an exception is thrown for any element in the bundle and it is not caught, it’ll cause the Flink job to be restarted. Flink runner then has to recreate the operators. The states of these operators will be restored from the last successful checkpoint. For example, the read offset of the recovered source operator will then have a safe offset to restart from. When running in streaming mode, unless a retry threshold is set, a bundle including a failing item will be retried indefinitely, which may cause the pipeline to permanently stall. So it is a must to catch all non-transient errors.&lt;/p&gt;

&lt;h2 id=&quot;handling-non-transient-errors&quot;&gt;Handling Non-Transient Errors&lt;/h2&gt;

&lt;h3 id=&quot;handling-with-a-tupletag&quot;&gt;Handling with a TupleTag&lt;/h3&gt;

&lt;p&gt;In this approach, exceptions caused due to non-transient errors should be caught within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DoFn.ProcessElement&lt;/code&gt; method. And we’d log the errors as we normally would. But instead of dropping the failed element, branch the outputs to write failed elements into a separate PCollection object as follows.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;processElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ProcessContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objectMapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;writeValueAsString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;LOG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;severe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Failed due to non-transient error {} - adding to dead letter queue&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sideOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deadLetterTupleTag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withOutputTags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;successTag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TupleTagList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deadLetterTag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These elements can then be written to a database, or a message queue for later inspection, by using another transform.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;outputPCollectionTupple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deadLetterTag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WriteToDeadLetterQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;handling-with-beams-withfailure&quot;&gt;Handling with Beam’s WithFailure&lt;/h3&gt;

&lt;p&gt;WithFailure is a type of exception handler provided by Beam for writing transforms that can handle exceptions raised during the processing of elements. The exception handler would receive an object of type WithFailures.ExceptionElement as the input along with the original input element that was being processed when the exception was raised.
WithFailure may not be suitable for transforms that may throw both transient, and non-transient errors. Since it would catch every type of exception, we won’t be able to utilize Flink’s retry capabilities even to retry transient errors.&lt;/p&gt;

&lt;h2 id=&quot;transient-errors-temporary&quot;&gt;Transient Errors (Temporary)&lt;/h2&gt;

&lt;p&gt;The DoFn’s may fail due to transient errors such as temporary outages, or exceptions thrown due to external service failures. Instead of catching such exceptions (dead letter queue approach), we could let Flink retry such failed operations.&lt;/p&gt;

&lt;p&gt;When a failure happens, Flink needs to restart the failed task and other affected tasks to recover the job to a normal state. Restart strategies and failover strategies are used to control the task restarting.&lt;/p&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
Checkpointing should be enabled explicitly, otherwise “no restart” strategy is used.
&lt;/div&gt;

&lt;p&gt;When checkpointing is enabled Flink would recover the state from the last successful checkpoint. By default ‘fixed-delay’ restart strategy is used for streaming jobs, with infinite retries every 10 seconds.&lt;/p&gt;

&lt;p&gt;The following pipeline options are provided by the Flink runner, which you could pass as program arguements to enable checkpointing and to adjust the application’s retry behavior.&lt;/p&gt;

&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th scope=&quot;col&quot;&gt;#&lt;/th&gt;
      &lt;th scope=&quot;col&quot; style=&quot;width: 40%;&quot;&gt;Option&lt;/th&gt;
      &lt;th scope=&quot;col&quot;&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th scope=&quot;row&quot;&gt;1&lt;/th&gt;
      &lt;td&gt;--checkpointingInterval&lt;/td&gt;
      &lt;td&gt;Checkpointing interval in milliseconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th scope=&quot;row&quot;&gt;2&lt;/th&gt;
      &lt;td&gt;--executionRetryDelay&lt;/td&gt;
      &lt;td&gt;Delay in milliseconds between retires&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th scope=&quot;row&quot;&gt;3&lt;/th&gt;
      &lt;td&gt;--numberOfExecutionRetries&lt;/td&gt;
      &lt;td&gt;You may use a larger value if you&apos;ve coded your app to retry only for transient errors. So the pipeline could eventually recover itself once the underlying error go away&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;h2 id=&quot;differentiate-between-transient--non-transient-errors&quot;&gt;Differentiate Between Transient &amp;amp; Non-Transient Errors&lt;/h2&gt;

&lt;p&gt;An error could be identified as a transient or non-transient error based on the Java type of the exception being thrown. Unless the exception is known to be due to a transient error (an error that could eventually recover by retrying), that exception should be considered as a non-transient error.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomDoFn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DoFn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@ProcessElement&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;processElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ProcessContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;handleException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handleException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Throwable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cause&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExceptionUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRootCause&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cause&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TransientErrorException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DoFn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ProcessContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To eliminate the need to write exception handling logic in every user-defined DoFn, you may define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomDoFn&lt;/code&gt; class that your other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DoFn&lt;/code&gt; classes could inherit from.&lt;/p&gt;

&lt;h2 id=&quot;how-exceptions-propagate&quot;&gt;How Exceptions Propagate&lt;/h2&gt;

&lt;p&gt;The following diagram shows how exceptions propagate in Apache Beam. Since transient exceptions are not caught, those exceptions will cause Flink’s restart strategy to kick in.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/apache-beam/beam-exception-propagation.png&quot; alt=&quot;Exception propagation in Apache Beam&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;recovery-and-retry-behavior&quot;&gt;Recovery and Retry Behavior&lt;/h2&gt;

&lt;p&gt;When a task failure happens, Flink restarts the failed task and other affected tasks. The last successful checkpoint is then used to recover the state including the corresponding stream positions.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/apache-beam/flink-restore-behavior.png&quot; alt=&quot;Retry and recovery behavior of Flink Runner&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Assume a scenario where the pipeline consumed four messages, M1, M2, M3, and M4. M1 and M2 were already sunk downstream. M3 and M4 are currently in processing.&lt;/p&gt;

&lt;p&gt;When PubsubIO is being used as the source operator, message acknowledgment happens at the time of checkpoint finalization. So in the above example, only M1, and M2 are acknowledged. Say the pipeline fails to process M4 due to a transient error, this would cause related tasks to be restarted starting from the last successful checkpoint. So M3 and M4 will be replayed, starting from the source operator.&lt;/p&gt;

&lt;p&gt;If the source operator is a KafkaIO for example, when the task restarts, the operator state will be recovered with properties such as the latest offset consumed so far, that are stored in the last successful checkpoint.&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="apache-beam" /><category term="flink" /><summary type="html">This guide discusses one of the approaches to retry errors when running Apache Beam applications with Apache Flink. While the approach discussed here could be applied to any Beam pipeline in general, decide and settle on an error handling strategy that suits your use case.</summary></entry><entry><title type="html">CVE-2021-44228 Fixing Log4J2 Vulnerability in Spring Boot</title><link href="https://www.linuxdeveloper.space/log4j-vulnerability-fix/" rel="alternate" type="text/html" title="CVE-2021-44228 Fixing Log4J2 Vulnerability in Spring Boot" /><published>2021-12-11T07:30:00+00:00</published><updated>2021-12-11T07:30:00+00:00</updated><id>https://www.linuxdeveloper.space/log4j-vulnerability-fix</id><content type="html" xml:base="https://www.linuxdeveloper.space/log4j-vulnerability-fix/">&lt;p&gt;&lt;strong&gt;How to check my application is vulnerable?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For your application to be vulnerable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-core&lt;/code&gt; has to be in your classpath.&lt;/p&gt;

&lt;p&gt;The vulnerability is only present in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-core&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.14.1&lt;/code&gt; and earlier versions.&lt;/p&gt;

&lt;p&gt;For Maven projects:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./mvnw dependency:list | grep log4j
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For Gradle:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./gradlew dependencies | grep log4j
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once you grep the console output, check whether log4j-core is present in your dependencies list. 
You can ignore &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-to-slf4j&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-api&lt;/code&gt; dependencies in your grep output as these two were included by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spring-boot-starter-logging&lt;/code&gt; and cannot be exploited on their own. 
Only applications that include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-core&lt;/code&gt; and accept user input to format log messages are vulnerable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your application is vulnerable consider one of the following fixes.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Upgrade log4j to 2.15.0 or newer&lt;/li&gt;
  &lt;li&gt;Remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.apache.logging.log4j.core.lookupJndiLookup&lt;/code&gt; class from the classpath&lt;/li&gt;
  &lt;li&gt;Switch to SLF4J&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Gayan Weerakutti</name></author><category term="linux" /><category term="security" /><category term="spring" /><summary type="html">How to check my application is vulnerable?</summary></entry><entry><title type="html">Running SonarQube in ECS</title><link href="https://www.linuxdeveloper.space/sonarqube-in-ecs/" rel="alternate" type="text/html" title="Running SonarQube in ECS" /><published>2021-02-24T18:00:00+00:00</published><updated>2021-02-24T18:00:00+00:00</updated><id>https://www.linuxdeveloper.space/sonarqube-in-ecs</id><content type="html" xml:base="https://www.linuxdeveloper.space/sonarqube-in-ecs/">&lt;p&gt;This guide briefs the steps required to deploy SonarQube Server in Amazon ECS. An ECS task definition needs to be created which is then used to launch SoanrQube as a service within Amazon ECS. Ready-made docker images for different SonarQube editions and versions can be found in Docker Hub, which we’ll be using for the deployment.&lt;/p&gt;

&lt;p&gt;Create an EFS file system to be used with SonarQube
When running SonarQube in ECS, persistent storage such as an EFS volume is required to prevent data loss. Otherwise, essential server data could be lost in case the container restarts or terminates. It also helps when updating the server to a new version or upgrading to a higher edition.&lt;/p&gt;

&lt;h1 id=&quot;create-ecs-task-definition&quot;&gt;Create ECS task definition&lt;/h1&gt;

&lt;p&gt;Make sure that the task execution IAM role has full access to the EFS created.&lt;/p&gt;

&lt;p&gt;Furthermore, this role should have the necessary permissions required to pull container images and to publish logs to Amazon CloudWatch.&lt;/p&gt;

&lt;h2 id=&quot;set-an-appropriate-task-size&quot;&gt;Set an appropriate task size&lt;/h2&gt;

&lt;p&gt;As mentioned in the docs, SonarQube server requires at least 2GB of RAM to run efficiently and 1GB of free RAM for the OS.&lt;/p&gt;

&lt;h2 id=&quot;volumes&quot;&gt;Volumes&lt;/h2&gt;

&lt;p&gt;Under volumes add the EFS file system that is being created for SonarQube.&lt;/p&gt;

&lt;h2 id=&quot;container-definitions&quot;&gt;Container definitions&lt;/h2&gt;

&lt;p&gt;Under container definitions, specify a SonarQube image as the image used to start your container. If this is image is being stored in ECR, make sure that the ECR Task execution IAM role has the permission to pull images from ECR.&lt;/p&gt;

&lt;h3 id=&quot;port-mappings&quot;&gt;Port mappings&lt;/h3&gt;

&lt;p&gt;The default port that SonarQube runs is “9000”. So under port mappings also set the container port to 9000.&lt;/p&gt;

&lt;h3 id=&quot;environment&quot;&gt;ENVIRONMENT&lt;/h3&gt;

&lt;p&gt;The default operating system limits on mmap counts are likely to be too low, which may result in out-of-memory exceptions. Therefore, SonarQube recommends that we set vm.max_map_count to a value greater than or equal to 524288. However, in ECS we can not control the ability to create memory maps.&lt;/p&gt;

&lt;p&gt;So disallow memory-mapping altogether,  enter the following Docker CMD parameters, into the input field named ‘Command’.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-Dsonar.search.javaAdditionalOpts=-Dnode.store.allow_mmap=false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;environment-variables&quot;&gt;Environment variables&lt;/h4&gt;
&lt;p&gt;The following environment variables should be set. These are referenced by the SonarQube docker image and is required to be able to successfully run the application.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SONAR_JDBC_URL
SONAR_JDBC_PASSWORD
SONAR_JDBC_USERNAME
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the JDBC URL is updated, the server ID, which is stored in the database will be re-generated and you’ll need a new license. So make sure to use an external database and to make backups.&lt;/p&gt;

&lt;h3 id=&quot;storage-and-logging&quot;&gt;STORAGE AND LOGGING&lt;/h3&gt;

&lt;p&gt;Under ‘STORAGE AND LOGGING’, add the following mount points to your EFS volume.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/opt/sonarqube/data
/opt/sonarqube/extensions
/opt/sonarqube/logs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;resource-limits&quot;&gt;RESOURCE LIMITS&lt;/h2&gt;

&lt;p&gt;The user running SonarQube should have permission to have at least 131072 open descriptors and should be able to open at least 8192 threads.&lt;/p&gt;

&lt;p&gt;Set the recommended Ulimits under ‘RESOURCE LIMITS’&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Limit name&lt;/strong&gt; .&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Soft limit&lt;/strong&gt; .&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Hard limit&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;NOFILE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;131072&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;131072&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NPROC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8192&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;8192&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;creating-the-sonarqube-service&quot;&gt;Creating the SonarQube Service&lt;/h1&gt;

&lt;p&gt;Now create a service from the task definition created. In the service configurations make sure to set FARGATE as the launch type. Set the ‘number of tasks’ to 1. Since, running multiple instances populating the same database is only supported by the Data Center Edition, and requires further configuration changes.&lt;/p&gt;

&lt;p&gt;Make sure that the security group attached to the service instance has an inbound rule that allows TCP 9000. Also add an inbound rule of type NFS, for the instance to be able to access the EFS volume created. Once the task is up and running, the SonarQube server should be accessible via the private IP of the running task and port 9000.&lt;/p&gt;

&lt;p&gt;Additionally, one could set up DNS routes, so to have convenient access to the server.&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="sonarqube" /><category term="ecs" /><summary type="html">This guide briefs the steps required to deploy SonarQube Server in Amazon ECS. An ECS task definition needs to be created which is then used to launch SoanrQube as a service within Amazon ECS. Ready-made docker images for different SonarQube editions and versions can be found in Docker Hub, which we’ll be using for the deployment.</summary></entry><entry><title type="html">Traverse Fractured Space Time - Indie Game Review</title><link href="https://www.linuxdeveloper.space/garvity-review/" rel="alternate" type="text/html" title="Traverse Fractured Space Time - Indie Game Review" /><published>2020-01-16T19:20:00+00:00</published><updated>2020-01-16T19:20:00+00:00</updated><id>https://www.linuxdeveloper.space/garvity-review</id><content type="html" xml:base="https://www.linuxdeveloper.space/garvity-review/">&lt;p&gt;&lt;em&gt;The following is a game review written by Wahaj, a tech enthusiast, writer, and aspiring physicist, about my first ever indie title, Gravity. Since this being a Linux blog, I’m also happy to announce that this game falls under the #MadeOnLinux category.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=defaulttm.gravity&quot;&gt;Gravity&lt;/a&gt; is a very recently released Android game from the indie developer Gayan Weerakutti. The developer has been working on the game part-time for over a year, making this something of a passion project. The game itself is a brain teaser style game with a Sci-Fi theme, and gameplay elements designed to match the theme.&lt;/p&gt;

&lt;h4 id=&quot;plot&quot;&gt;Plot&lt;/h4&gt;

&lt;p&gt;The plot is fairly simple and straightforward and is only really explained at the beginning of the game. In its search for new resources and exploration, it has run out of resources and is in significant danger. Humanity is now relying on a single explorer to do whatever they can to guide humanity back to stability. The writing is pretty basic and there is a lot to be fleshed out, but the story only plays a small part in the game so it is not a huge bother.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/o4vJ0LMbyU4&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h4 id=&quot;gameplay&quot;&gt;Gameplay&lt;/h4&gt;

&lt;p&gt;The gameplay, like the plot, is fairly simple. However, this time, it plays into the game’s advantage, as it leads to a nice intuitive experience. This is how it works: you move your character across some tiles, and you need to avoid the black holes and reach the final destination. However, there’s a catch. On alternating turns, you can only move 1 tile and 3 tiles. This is supposed to represent the 4-dimensional structure of space-time being fractured. There are an additional element of power-ups that are unlocked as you progress in the game. The puzzles can be challenging and if you don’t think them through, some of them are really difficult. However, they are fun at the same time. As you move on, additional gameplay elements that make the puzzles a bit more complex, however, without losing the games inherent intuitive simpleness.&lt;/p&gt;

&lt;h4 id=&quot;visuals-and-audio&quot;&gt;Visuals and Audio&lt;/h4&gt;

&lt;p&gt;The game incorporates soothing music, reminiscent of a lot of minimalist indie games and that’s certainly a nice thing and makes the experience a relaxing one, where you can just wind down. The same goes for the visuals, which are heavily Sci-Fi themed. Your character is an astronaut, walking across the background of space.&lt;/p&gt;

&lt;h4 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Overall, Gravity looks like a nice indie game that combines a lot of simple but fun gameplay elements, along with charming visuals and sounds. It even manages to have no forced ads that would distract you, despite being available for free on the Google Play Store.&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="gaming" /><summary type="html">The following is a game review written by Wahaj, a tech enthusiast, writer, and aspiring physicist, about my first ever indie title, Gravity. Since this being a Linux blog, I’m also happy to announce that this game falls under the #MadeOnLinux category.</summary></entry><entry><title type="html">SonarQube Pull Request Decoration</title><link href="https://www.linuxdeveloper.space/sonarqube-pr-decoration/" rel="alternate" type="text/html" title="SonarQube Pull Request Decoration" /><published>2019-11-24T05:30:18+00:00</published><updated>2019-11-24T05:30:18+00:00</updated><id>https://www.linuxdeveloper.space/sonarqube-pr-decoration</id><content type="html" xml:base="https://www.linuxdeveloper.space/sonarqube-pr-decoration/">&lt;h4 id=&quot;pull-request-decoration-did-not-happen&quot;&gt;Pull request decoration did not happen&lt;/h4&gt;

&lt;p&gt;If you got this warning I recommend that you first enable debug logs on your SonarQube server. Then perform a pull request analysis again while inspecting the &lt;a href=&quot;https://docs.sonarqube.org/latest/instance-administration/system-info/#header-2&quot;&gt;ce.log&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tail --follow sonar-dir/logs/ce.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you see these warnings, most probably the system clock of your server is to blame.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;GET response did not have expected HTTP code (was 401): {“message”:”‘Issued at’ claim (‘iat’) must be an Integer representing the time that the assertion was issued”,“documentation_url”:“https://developer.github.com/enterprise/2.18/v3”}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pull request decoration did not happen. Please install SonarQube Github application on the repository’s organization or user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To synchronize a system clock to real time, the most recommended solution is to install is chrony.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install chrony
sudo systemctl restart chrony.service
sudo systemctl enable chrony.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If using a RHEL based distro, run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum install chrony
systemctl start chronyd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To check whether there is an actual time drift, issue the following command&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ chronyc tracking
Reference ID    : A9FEA97B (169.254.169.123)
Stratum         : 4
Ref time (UTC)  : Sun Nov 24 15:45:37 2019
System time     : 46.211318970 seconds fast of NTP time
Last offset     : -0.000026256 seconds
RMS offset      : 0.002788091 seconds
Frequency       : 41.560 ppm fast
Residual freq   : -0.005 ppm
Skew            : 5.294 ppm
Root delay      : 0.000519169 seconds
Root dispersion : 0.000747741 seconds
Update interval : 71.3 seconds
Leap status     : Normal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you could see from the output, my System time was drifted by about 46 seconds. If there is a time drift, chrony will automatically adjust the clock gradually. You can verify that by issuing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ chronyc tracking&lt;/code&gt; command and observing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System time&lt;/code&gt; line of the output. Once the ‘System time’ property is driven closer to zero, you could try re-running a PR analysis and PR decoration should work fine.&lt;/p&gt;

&lt;h1 id=&quot;socket-time-out&quot;&gt;Socket time out&lt;/h1&gt;

&lt;p&gt;Increase javaOpts …&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="jekyll" /><category term="update" /><summary type="html">Pull request decoration did not happen</summary></entry><entry><title type="html">Install Unity3D on Linux</title><link href="https://www.linuxdeveloper.space/install-unity-linux/" rel="alternate" type="text/html" title="Install Unity3D on Linux" /><published>2019-01-06T17:02:23+00:00</published><updated>2019-01-06T17:02:23+00:00</updated><id>https://www.linuxdeveloper.space/install-unity-linux</id><content type="html" xml:base="https://www.linuxdeveloper.space/install-unity-linux/">&lt;p&gt;I’ve been running Unity on my Debian / Ubuntu machines for so long and never have any issues whatsoever. As of now Ubuntu 18.04, and CentOS 7 are listed as the officially supported distros. I’m currently developing a sci-fi brain teaser which is currently on closed beta on Google Play, is solely build on Unity Linux. Again, it’s no different from running it on a Windows machine.&lt;/p&gt;

&lt;p&gt;The preferred way of installing Unity on Linux is by first installing Unity Hub.&lt;/p&gt;

&lt;h4 id=&quot;install--run-unity-hub-on-linux&quot;&gt;Install &amp;amp; Run Unity Hub on Linux&lt;/h4&gt;

&lt;p&gt;You can find the Unity Hub setup file in here:&lt;/p&gt;

&lt;p&gt;https://public-cdn.cloud.unity3d.com/hub/prod/UnityHub.AppImage&lt;/p&gt;

&lt;p&gt;You can also refer to &lt;a href=&quot;https://forum.unity.com/forums/unity-hub.142/&quot;&gt;Unity Hub sub-forum&lt;/a&gt; in forum.unity.com for additional information and to make sure that you’re downloading the latest available version.&lt;/p&gt;

&lt;p&gt;Once downloaded, you may need to give execute permission to the UnityHubSetup.AppImage&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /path/to/download/dir
&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x UnityHub.AppImage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then run the setup file. Either run it from the terminal or just open the file from a file manager.&lt;/p&gt;

&lt;h4 id=&quot;install-unity-from-unity-hub&quot;&gt;Install Unity from Unity Hub&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;/assets/unity/running-unity-hub.gif&quot; target=&quot;_blank&quot;&gt;
&lt;img src=&quot;/assets/unity/running-unity-hub.gif&quot; alt=&quot;Running Unity Hub&quot; width=&quot;100%&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Installs section of Unity Hub application, you can choose a preferred version of Unity that you want to
install. Unity Hub will automatically download and install it for you. One can have several Unity versions installed. Unity Hub allows you to easily switch between those different versions of Unity.&lt;/p&gt;

&lt;p&gt;Unity recommends that we use Unity Hub for creating, opening, and managing all the projects. So always use Unity Hub instead of directly running a specific Editor version which usually gets installed under ~/Unity/Hub/Editor/[Version]. You may create a shortcut to your UnityHub.AppImage file for convenience.&lt;/p&gt;

&lt;h4 id=&quot;unity-crash&quot;&gt;Unity Crash&lt;/h4&gt;

&lt;p&gt;If your Unity crashes, most probably your graphics driver is to blame.&lt;/p&gt;

&lt;p&gt;If you have an Intel graphic card that is 2007 or newer, try uninstalling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xserver-xorg-video-intel&lt;/code&gt;.
Your system will then default to use the builtin modesetting driver instead.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; xserver-xorg-video-intel
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get purge xserver-xorg-video-intel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If that still not fix your issue, try asking in the forums.&lt;/p&gt;

&lt;p&gt;If it’s not a known issue, you could always send a bug report by opening an issue in &lt;a href=&quot;https://issuetracker.unity3d.com/&quot;&gt;Issue Tracker&lt;/a&gt; and Unity team probably will get back to you.&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="linux" /><category term="unity" /><summary type="html">I’ve been running Unity on my Debian / Ubuntu machines for so long and never have any issues whatsoever. As of now Ubuntu 18.04, and CentOS 7 are listed as the officially supported distros. I’m currently developing a sci-fi brain teaser which is currently on closed beta on Google Play, is solely build on Unity Linux. Again, it’s no different from running it on a Windows machine.</summary></entry><entry><title type="html">Recovering corrupted NTFS partitions in a Linux machine</title><link href="https://www.linuxdeveloper.space/recovering-corrupted-ntfs-partitions/" rel="alternate" type="text/html" title="Recovering corrupted NTFS partitions in a Linux machine" /><published>2018-08-14T05:12:18+00:00</published><updated>2018-08-14T05:12:18+00:00</updated><id>https://www.linuxdeveloper.space/recovering-corrupted-ntfs-partitions</id><content type="html" xml:base="https://www.linuxdeveloper.space/recovering-corrupted-ntfs-partitions/">&lt;h4 id=&quot;what-if-my-partition-is-not-showing-up-or-gone-missing&quot;&gt;What if my partition is not showing up or gone missing?&lt;/h4&gt;

&lt;p&gt;In that case, TestDisk could help. It is a disk utility designed to help people recover their lost partitions.&lt;/p&gt;

&lt;p&gt;To install it, here in my case on Debian, I’ll do&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo apt-get install testdisk
$ testdisk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;TestDisk has a QUICK SEARCH option which can search and list all your missing partitions if there’s any. Most probably your missing partitions should have appeared by now. If not, try running a DEEPER SEARCH. Once it found any, use the WRITE option of TestDisk which will re-write the partition table for you.&lt;/p&gt;

&lt;p&gt;Restart your computer and your missing partitions should now show up.&lt;/p&gt;

&lt;p&gt;I won’t go into detail. For a more thorough guide, follow the &lt;a href=&quot;https://www.cgsecurity.org/wiki/TestDisk_Step_By_Step&quot;&gt;Step By Step guide&lt;/a&gt; from the official Wiki.&lt;/p&gt;

&lt;h4 id=&quot;how-to-fix-when-my-ntfs-goes-raw&quot;&gt;How to fix when my NTFS goes RAW?&lt;/h4&gt;

&lt;p&gt;It’s better to use Windows utilities when it comes to dealing with NTFS.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Boot into a Windows Recovery Disk.&lt;/li&gt;
  &lt;li&gt;Then go into ‘System Recovery Options’ menu.&lt;/li&gt;
  &lt;li&gt;Open the command prompt window.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use one or more of the following commands to find out the label of your corrupted partition.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; diskpart list disk
 diskpart select disk
 diskpart list volumes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Once done exit from diskpart and run&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; chkdsk /f /r D:
 where D: is the drive letter of the corrupted partition. 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have got better solutions, let us know in the comment section.&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="linux" /><summary type="html">What if my partition is not showing up or gone missing?</summary></entry><entry><title type="html">Fixing JHBuild Errors</title><link href="https://www.linuxdeveloper.space/fixing-jhbuild-issues/" rel="alternate" type="text/html" title="Fixing JHBuild Errors" /><published>2018-08-14T05:12:18+00:00</published><updated>2018-08-14T05:12:18+00:00</updated><id>https://www.linuxdeveloper.space/fixing-jhbuild-issues</id><content type="html" xml:base="https://www.linuxdeveloper.space/fixing-jhbuild-issues/">&lt;p&gt;&lt;strong&gt;Fixing no native package found errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JHBuild uses apt-file to locate packages in which a given file belongs to.&lt;/p&gt;

&lt;p&gt;When apt-file cannot locate the relevant packages for you, JHBuild would give you with informational warnings such as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I: Installing dependencies on system: libsystemd-journal libtiff
I: Using apt-file to search for providers; this may be slow. Please wait.
I: No native package found for libsystemd-journal (/libsystemd-journal.pc)
I: No native package found for libtiff (/usr/include/tiff.h)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In such cases, first make sure that your apt-file database is up-to-date.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-file update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then re-run the process. JHBuild might still fails to complete the process. This could be due to several reasons. So for instance if apt-file finds several packages which includes the same file, JHBuild would fail to decide on which package to install. In that case we’d have to find the most appropriate pacakge and install it manaully. Also the actual package name can be sligtly different from the name stated in the warning.&lt;/p&gt;

&lt;p&gt;To find the relevant package which includes the given file, you could run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt-file search path/to/missing.file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You could also use Ubuntu’s package archive search on web, instead of apt-file. But apt-file usually is more convenient.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Go to packages.ubuntu.com&lt;/li&gt;
  &lt;li&gt;Search the contents of packages which include the missing file.&lt;/li&gt;
  &lt;li&gt;Find the relevant package for your distribution and install it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example here the missing libsystemd.pc belongs to the package named ‘libsystemd-dev’&lt;/p&gt;

&lt;p&gt;Therefore running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get install libsystemd-dev&lt;/code&gt; should fix it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixing No matching system package installed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This type of errors can be quite tricky as your distribution might not have a package that is newer than the required version.&lt;/p&gt;

&lt;p&gt;Example cases:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;libsystemd-journal (libsystemd-journal.pc, required=201)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ubuntu’s Launchpad provides compatibility package for libsystemd-journal-dev (&amp;gt;201) which includes the required .pc file. Downloading and installing latest binary .deb file for your distribution should fix it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixing configure errors: Package requirements (package-name) were not met&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In that case do,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt-cache search package-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will list down all the packages for the given keyword: package-name&lt;/p&gt;

&lt;p&gt;Find the required development package from the list and install it.
On a Debian based system the package name would probably contain a *-dev suffix. For Fedora, look for ‘-devel’&lt;/p&gt;

&lt;p&gt;For example to fix &lt;em&gt;“configure: error: Package requirements (libselinux &amp;gt;= 2.0) were not met”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Run the following in a terminal&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt-cache search libselinux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On my system the output is,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;libselinux1 - SELinux runtime shared libraries
libselinux1-dev - SELinux development headers
libsemanage1 - SELinux policy management library
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So installing ‘libselinux1-dev’ should fix the configure error.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt-get install libselinux1-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Gayan Weerakutti</name></author><category term="linux" /><summary type="html">Fixing no native package found errors</summary></entry><entry><title type="html">Install Windows after Ubuntu/Linux</title><link href="https://www.linuxdeveloper.space/install-windows-after-linux/" rel="alternate" type="text/html" title="Install Windows after Ubuntu/Linux" /><published>2017-10-11T05:30:18+00:00</published><updated>2017-10-11T05:30:18+00:00</updated><id>https://www.linuxdeveloper.space/install-windows-after-linux</id><content type="html" xml:base="https://www.linuxdeveloper.space/install-windows-after-linux/">&lt;p&gt;As you know, the most common, and probably the most recommended way of dual booting Ubuntu and Windows is to install Windows first and then Ubuntu. But what if you want to install Windows second on a computer with Ubuntu/Linux already installed?&lt;/p&gt;

&lt;p&gt;This guide assumes that you have Ubuntu already installed on your system, and will guide you through installing Windows 7/8/8.1/10 when you have a working Ubuntu/Linux partition.&lt;/p&gt;

&lt;p&gt;The problem here is that the Windows installer tends to overwrite Grub bootloader or whatever making only the Windows installation bootable. But the good news is that your Linux partition is untouched, including the original bootloader and the other Grub configurations. So restoring or recovering Grub is just a matter of running a few commands on the terminal.&lt;/p&gt;

&lt;h4 id=&quot;install-windows-on-a-separate-partition&quot;&gt;Install Windows on a Separate Partition&lt;/h4&gt;

&lt;p&gt;If your Ubuntu installation occupies the entire hard drive, to be able to create free space for the Windows installation, you may have to shrink an existing partition using a disk utility like GParted. GParted comes preinstalled on Ubuntu LiveCD.&lt;/p&gt;

&lt;h4 id=&quot;boot-into-a-windows-installation-media-and-complete-the-installation&quot;&gt;Boot into a Windows installation media and complete the installation&lt;/h4&gt;

&lt;p&gt;Once installed, because of Microsoft’s false assumption that there are no non-Microsoft operating systems you’ll be taken straight into Windows.&lt;/p&gt;

&lt;h4 id=&quot;restore--reinstall-grub-2-with-a-ubuntu-live-media&quot;&gt;Restore / Reinstall Grub 2 with a Ubuntu Live Media&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Now boot into a Ubuntu Live/USB or CD.&lt;/li&gt;
  &lt;li&gt;Open a terminal. (Ctrl + Alt + t)&lt;/li&gt;
  &lt;li&gt;Use a command like lsblk, blkid or GParted to identify your Linux root, and boot partitions. You may or may not have a separate boot partition.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Find Linux Partitions&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ lsblk -f
 NAME                  FSTYPE     MOUNTPOINT
 sda                                                                            
 ├─sda1                ext4       /boot
 ├─sda2                ext4       /
 ├─sda3                ntfs       
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;In my case,&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda1&lt;/code&gt; is the Linux boot partition&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda2&lt;/code&gt; is the Linux root partition&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda3&lt;/code&gt; is the Windows partition&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Setup a Chroot Environment&lt;/p&gt;

    &lt;p&gt;Now we’ll be repairing our old grub bootloader in a chroot environment.&lt;/p&gt;

    &lt;p&gt;Mount your root filesystem under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt&lt;/code&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; sudo mount /dev/sda2 /mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;blockquote&gt;
      &lt;p&gt;If you’re using BTRFS (New Linux B-Tree File System) instead of EXT4, the above command should change to 
sudo mount -t btrfs -o subvol=@ /dev/sda2 /mnt/&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls /mnt&lt;/code&gt; to verify that the correct partition is mounted. It should list the content of your root.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ ls /mnt
 bin   dev  home        lib64       media  opt   root  sbin  sys  usr  vmlinuz
 boot  etc  initrd.img  lost+found  mnt    proc  run   srv   tmp  var  vmlinuz.old
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Mount the boot partition. (SKIP if you don’t have a separate boot partition)&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; sudo mount /dev/sda1 /mnt/boot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If you have an EFI partition you should mount that also. It is basically a small FAT32 partition around 100mb. Please refer to the section on how to &lt;a href=&quot;#reinstalling-grub-in-an-efi-based-system&quot;&gt;reinstall Grub in an EFI system&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Bind these directories, so grub can detect other operating systems, like so.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;--bind&lt;/span&gt; /dev /mnt/dev
 &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;--bind&lt;/span&gt; /dev/pts /mnt/dev/pts
 &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;--bind&lt;/span&gt; /proc /mnt/proc
 &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;--bind&lt;/span&gt; /sys /mnt/sys
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Let’s chroot into our existing Ubuntu/Linux system on the hard disk.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; sudo chroot /mnt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Reinstall Grub.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; grub-install /dev/sda &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;specify the disk &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/dev/sdX&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;, not &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/dev/sdaX&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
 grub-install &lt;span class=&quot;nt&quot;&gt;--recheck&lt;/span&gt; /dev/sda
 &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Once you’ve successfully reinstalled Grub, restart the computer. On next reboot Grub will be the default bootloader and you’ll be presented with a list of operating systems to choose from (Ubuntu and Windows, of course).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;reinstalling-grub-in-an-efi-based-system&quot;&gt;Reinstalling Grub in an EFI Based System&lt;/h4&gt;

&lt;p&gt;Reinstalling Grub bootloader in a UEFI based computer is no different from installing Grub on a legacy BIOS system. Here we also mount the EFI partition before chrooting, as we’d do with the boot partition.&lt;/p&gt;

&lt;h5 id=&quot;case-2&quot;&gt;Case #2&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lsblk -f
NAME                  FSTYPE     MOUNTPOINT
sda                                                                            
├─sda1                ext4       /boot/efi
├─sda2                ext4       /
├─sda3                ntfs       
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda1&lt;/code&gt; is the EFI partition and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda2&lt;/code&gt; is the root.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo mount /dev/sda2 /mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mount EFI partition under ‘/mnt/boot/efi’&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo mount /dev/sda1 /mnt/boot/efi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Forgetting to do so will result in errors being thrown while trying to execute grub-install: “/boot/efi does not appear to be the EFI partition”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As shown previously, bind the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/pts&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys&lt;/code&gt; directories.&lt;/p&gt;

&lt;p&gt;Finally,&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo chroot&lt;/span&gt; /mnt
grub-install
&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In some rare occasions, Grub might not detect Windows. In that case just login to Ubuntu (installed one on the disk, not the bootable Live USB/CD) and execute,&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;os-prober
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-grub
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Happy Dual-Booting!&lt;/p&gt;</content><author><name>Gayan Weerakutti</name></author><category term="jekyll" /><category term="update" /><summary type="html">As you know, the most common, and probably the most recommended way of dual booting Ubuntu and Windows is to install Windows first and then Ubuntu. But what if you want to install Windows second on a computer with Ubuntu/Linux already installed?</summary></entry></feed>