<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>mai1015</title>
 <link href="https://www.mai1015.com//atom.xml" rel="self"/>
 <link href="https://www.mai1015.com//"/>
 <updated>2021-02-01T21:14:42+00:00</updated>
 <id>https://www.mai1015.com/</id>
 <author>
   <name>mai1015</name>
   <email>i#mai1015.com</email>
 </author>

 
 <entry>
   <title>Microk8s Install Cert-manager</title>
   <link href="https://www.mai1015.com//kubernetes/2021/02/01/Microk8s-certmanger/"/>
   <updated>2021-02-01T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//kubernetes/2021/02/01/Microk8s-certmanger</id>
   <content type="html">&lt;h1 id=&quot;install&quot;&gt;Install&lt;/h1&gt;
&lt;p&gt;First you will need to install microk8s and enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helm3&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ingress&lt;/code&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;microk8s enable helm3 ingress&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then install cert-manager with helm with following cmd by (Envekus)[https://www.reddit.com/r/kubernetes/comments/g3z5sp/microk8s_with_certmanager_and_letsecncrypt/].&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;microk8s kubectl create namespace cert-manager
microk8s helm3 repo add jetstack https://charts.jetstack.io
microk8s helm3 repo update
microk8s helm3 &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cert-manager jetstack/cert-manager &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--namespace&lt;/span&gt; cert-manager &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt; v0.15.2 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;installCRDs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; ingressShim.defaultIssuerName&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;letsencrypt-production &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; ingressShim.defaultIssuerKind&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ClusterIssuer &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; ingressShim.defaultIssuerGroup&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cert-manager.io
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then setup cluster issuer with the following cmd.&lt;/p&gt;
&lt;div class=&quot;language-yaml 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;s&quot;&gt;microk8s kubectl apply -f - &amp;lt;&amp;lt;YAML&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cert-manager.io/v1alpha2&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ClusterIssuer&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;letsencrypt-production&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;acme&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CHANGE-ME@example.com&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://acme-v02.api.letsencrypt.org/directory&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;privateKeySecretRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;letsencrypt-production-issuer-account-key&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;solvers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;{}&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;http01&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;ingress&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;public&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;YAML&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Then you will be able to gerenate the certificate. The ingress class in microk8s is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public&lt;/code&gt; for me. Otherwise, it is not generating endpoint for ACME validation.&lt;/p&gt;
&lt;div class=&quot;language-yaml 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;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;networking.k8s.io/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Ingress&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;default&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;kubernetes.io/ingress.class&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;public&quot;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;cert-manager.io/cluster-issuer&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;letsencrypt-production&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tls&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;secretName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example-tls-acme&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8080&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Alipay Sdk Learn</title>
   <link href="https://www.mai1015.com//2021/01/31/Alipay-SDK-learn/"/>
   <updated>2021-01-31T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//2021/01/31/Alipay-SDK-learn</id>
   <content type="html">
</content>
 </entry>
 
 <entry>
   <title>Istio Upstream Connection Overflow</title>
   <link href="https://www.mai1015.com//kubernetes/2021/01/20/Istio-Upstream-Connection-Overflow/"/>
   <updated>2021-01-20T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//kubernetes/2021/01/20/Istio-Upstream-Connection-Overflow</id>
   <content type="html">&lt;h2 id=&quot;backgroun&quot;&gt;Backgroun&lt;/h2&gt;
&lt;p&gt;I found some failed request 503 error for the microservice deployment in Openshift 4.5 with Service Mesh v1. The error shown is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upstream connect error or disconnect/reset before headers. reset reason: overflow&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;
&lt;p&gt;I found the solution during the search and refer to the documentation. It is because Service Mesh v1 is using (Istio 1.3)[https://istio.io/v1.3/docs/reference/config/networking/v1alpha3/destination-rule/#ConnectionPoolSettings-HTTPSettings]. And the Connection poll is set to 1024 for http1MaxPendingRequests, http2MaxRequests, etc. It is different from version 1.8 where it is default to 2^32-1. Therefore, it is required to set it differently.&lt;/p&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;This is not really a good solution I believe. and it require sometime to investigate, but you can increase those settings with destination rules.&lt;/p&gt;
&lt;div class=&quot;language-yaml 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;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;networking.istio.io/v1alpha3&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DestinationRule&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sample-destinationrule&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sample&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;trafficPolicy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;loadBalancer&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;simple&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;RANDOM&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;connectionPool&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;http1MaxPendingRequests&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10240&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;http2MaxRequests&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10240&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;subsets&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;v1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Kubernetes Debugging Network</title>
   <link href="https://www.mai1015.com//kubernetes/2020/12/15/kube-debug/"/>
   <updated>2020-12-15T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//kubernetes/2020/12/15/kube-debug</id>
   <content type="html">&lt;p&gt;When you try to debug the network inside kubernetes but not much tool avaliable since all the image remove unused command. The easy way to to use busybox by deploying a pod using the following commandline &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl run -i --tty --rm debug --image=busybox --restart=Never -- sh&lt;/code&gt;. Then you can access to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;telnet&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nc&lt;/code&gt;, etc.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kube Rolling Update</title>
   <link href="https://www.mai1015.com//2020/11/15/kube-rolling-update/"/>
   <updated>2020-11-15T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//2020/11/15/kube-rolling-update</id>
   <content type="html">&lt;p&gt;https://stackoverflow.com/questions/53591417/kubernetes-kubectl-apply-does-not-update-pods-when-using-latest-tag&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using ESLint and Prettier with React</title>
   <link href="https://www.mai1015.com//php/2020/07/20/react-eslint-prettier/"/>
   <updated>2020-07-20T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//php/2020/07/20/react-eslint-prettier</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://thomlom.dev/setup-eslint-prettier-react/&quot;&gt;How to setup ESLint and Prettier for your React apps&lt;/a&gt;
&lt;a href=&quot;https://dev.to/robertcoopercode/using-eslint-and-prettier-in-a-typescript-project-53jb&quot;&gt;Using ESLint and Prettier in a TypeScript Project&lt;/a&gt;
&lt;a href=&quot;https://github.com/ionic-team/eslint-config-ionic/blob/master/index.js&quot;&gt;eslint-config-ionic&lt;/a&gt;
&lt;a href=&quot;https://khalilstemmler.com/blogs/typescript/eslint-for-typescript/&quot;&gt;How to use ESLint with TypeScript&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RCF2047 mutipart form decode for php</title>
   <link href="https://www.mai1015.com//php/2020/05/09/rcf2047-form-php/"/>
   <updated>2020-05-09T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//php/2020/05/09/rcf2047-form-php</id>
   <content type="html">&lt;p&gt;Sometime, there are error on the php backend when uploading the file.
When I check the form data and it was encoded with RCF2047.&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;=?utf-8?B?L2RhdGEvdXNlci8wL2NvbS5mdXp6eXBhd3Muc25zL2ZpbGVzL+iMuOS5i+eIqsK356S+5Yy6L0ltYWdlcy8yMDIwMDUwODIyNTExMjMzODMuanBlZw==?=
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This is because the file path contains non-US ACSII character, so the request programe will try to encode it first. There is no way to extract file name from the raw data.
The easy way to solve it is using &lt;a href=&quot;https://www.php.net/manual/en/function.iconv-mime-decode.php&quot;&gt;iconv_mime_decode&lt;/a&gt; function to decode the file name first.&lt;/p&gt;

&lt;div class=&quot;language-php 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;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;iconv_mime_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'=?utf-8?B?L2RhdGEvdXNlci8wL2NvbS5mdXp6eXBhd3Muc25zL2ZpbGVzL+iMuOS5i+eIqsK356S+5Yy6L0ltYWdlcy8yMDIwMDUwODIyNTExMjMzODMuanBlZw==?='&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt; The filename will output correctly.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TS2345 error using react-redux connect</title>
   <link href="https://www.mai1015.com//javascript/2020/05/05/react-redux-ts2345/"/>
   <updated>2020-05-05T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//javascript/2020/05/05/react-redux-ts2345</id>
   <content type="html">&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@type/react-redux@6.0.6&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;npm i --save-dev @type/react-redux@6.0.6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Then it will be ready to go.&lt;/p&gt;

&lt;h2 id=&quot;what-cause-the-problem&quot;&gt;What cause the problem&lt;/h2&gt;
&lt;p&gt;When trying to connect state with connect function shown belown.&lt;/p&gt;

&lt;div class=&quot;language-ts 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;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ILoginProps&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;StateProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DispatchProps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ILoginProps&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/** codes omitted **/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapStateToProps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authentication&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;IRootState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;isAuthenticated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isAuthenticated&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapDispatchToProps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loginUser&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;StateProps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReturnType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapStateToProps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DispatchProps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapDispatchToProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;mapStateToProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;mapDispatchToProps&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The newer @type/react-redux@7.1.7 is likely to cause problem because it is trying to resolve the dispatch function into different form.&lt;/p&gt;

&lt;div class=&quot;language-ts 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;c1&quot;&gt;// from&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loginUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rememberMe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// to&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loginUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rememberMe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will cause this extend &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILoginProps&lt;/code&gt; does not match with type expected with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connect()&lt;/code&gt; function.&lt;/p&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;Therefore, the easy is to downgrade by install the package below.
The other way is to manually write the prop interface.&lt;/p&gt;
&lt;div class=&quot;language-ts 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;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ILoginProps&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;StateProps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;loginUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After more search, I found this &lt;a href=&quot;https://stackoverflow.com/questions/58939260/incompatible-props-void-not-assignable-to-thunkaction&quot;&gt;answer&lt;/a&gt;. The &lt;a href=&quot;https://react-redux.js.org/using-react-redux/static-typing#typing-the-connect-higher-order-component&quot;&gt;document&lt;/a&gt; also has more information. 
This is another way to solve the problem.&lt;/p&gt;
&lt;div class=&quot;language-ts 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;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ILoginProps&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropsConnected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapStateToProps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authentication&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;IRootState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;isAuthenticated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isAuthenticated&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapDispatchToProps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loginUser&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;connector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;nx&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;mapStateToProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;mapDispatchToProps&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropsConnected&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ConnectedProps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;connector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;connector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Spring Boot Autowiring Multiple implementation for Interface</title>
   <link href="https://www.mai1015.com//java/2019/12/24/spring-boot-multiple-implementations/"/>
   <updated>2019-12-24T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//java/2019/12/24/spring-boot-multiple-implementations</id>
   <content type="html">&lt;p&gt;Autowiring is a convenient feature for development. Developers do not require to handle object creation, the application can help decide the object/s that a service or controller required to work.&lt;/p&gt;

&lt;p&gt;When specifying a class, sometimes it is necessary to have an interface so you can make different implementation. However, it might confuse the application since it cannot choose the correct bean. There are ways to solve the problem.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Primary annotation.&lt;/p&gt;

    &lt;p&gt;If you have multiple implementations, you can choose the one that is primarily used. Then apply &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Primary&lt;/code&gt;, the application will automate wire all related interface to this implementation.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&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;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;a&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;nd&quot;&gt;@Service&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Primary&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Service&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&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;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;So the application will link it to class B.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Qualifier annotation&lt;/p&gt;

    &lt;p&gt;If you need to choose between different implementation, you should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Qualifier&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&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;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;a&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;nd&quot;&gt;@Service&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Qualifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;firstService&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Service&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Qualifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;secondService&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&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;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;If you need implementation C, you can specify with `@Qualifier`.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&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;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FirstManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Autowired&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// inject FirstServiceImpl&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FirstManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Qualifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;secondService&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Reference: &lt;a href=&quot;https://stackoverflow.com/questions/51766013/spring-boot-autowiring-an-interface-with-multiple-implementations&quot;&gt;link&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Testing in Spring Boot with JPA</title>
   <link href="https://www.mai1015.com//java/2019/12/23/test-spring-boot-jpa/"/>
   <updated>2019-12-23T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//java/2019/12/23/test-spring-boot-jpa</id>
   <content type="html">&lt;p&gt;Application needs to be tested. Here are some notes to test spring boot application.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Deploy kubernetes and helm (国内部署 kubernetes)</title>
   <link href="https://www.mai1015.com//linux/2019/08/13/deploy-kubernetes-and-helm-with-gitlab/"/>
   <updated>2019-08-13T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//linux/2019/08/13/deploy-kubernetes-and-helm-with-gitlab</id>
   <content type="html">&lt;p&gt;国内部署 k8s 是真的难，坑太多了。这两个花了两天终于成功部署一个能用都了&lt;/p&gt;

&lt;h1 id=&quot;尝试&quot;&gt;尝试&lt;/h1&gt;
&lt;p&gt;首先，我从alpine系统下尝试部署，可是源里面都 test kubernetes 不能用。运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubeadm init&lt;/code&gt; 每次都是部署失败，即使kubelet启动成功了。但是卡在docker这里，因为其他组件都不会成功运行。日志也没有任何相关资料，github上都问题解决方案都没有用。所以，必须得换一个系统。 并且国内墙了google，源都不能访问。&lt;/p&gt;

&lt;h1 id=&quot;过程&quot;&gt;过程&lt;/h1&gt;
&lt;p&gt;我选用了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Debian 10&lt;/code&gt;作为我都主系统。&lt;/p&gt;
&lt;h2 id=&quot;docker&quot;&gt;Docker&lt;/h2&gt;
&lt;p&gt;安装完成后，可以直接通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl https://get.docker.com/ | bash -&lt;/code&gt; 来安装docker。
不知道为什么 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Debian 10&lt;/code&gt; 安装不上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cri-o&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; 用起来也没问题，所以就不在这里纠结了。
然后检查一下运行状况，没问题，修改一下配置。&lt;/p&gt;
&lt;div class=&quot;language-json 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;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;exec-opts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;native.cgroupdriver=systemd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;log-driver&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;json-file&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;log-opts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;max-size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;100m&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;insecure-registries&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;10.0.1.121:5000&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1:5000&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;registry-mirrors&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://************.myhuaweicloud.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;storage-driver&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;overlay2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data-root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/mnt/docker&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里我配置了华为的镜像，需要先在&lt;a href=&quot;https://mirrors.huaweicloud.com/&quot;&gt;这里&lt;/a&gt;注册，就能获取一个链接。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubeadm&lt;/code&gt; 推荐&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 作为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cgroup&lt;/code&gt; 的驱动，所以改动一下。&lt;/p&gt;

&lt;h2 id=&quot;kubernetes&quot;&gt;Kubernetes&lt;/h2&gt;
&lt;p&gt;之后就可以开始安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k8s&lt;/code&gt;了。
参考了一下这些文章：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.csdn.net/tete2csdn/article/details/89405672&quot;&gt;debian9.8搭建kubernetes多主节点集群(一)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.51cto.com/xudate/2150607&quot;&gt;kubernetes遇到问题&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://segmentfault.com/a/1190000017010166&quot;&gt;k8s 1.12.1 的坑和解决方法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://my.oschina.net/eima/blog/1860598&quot;&gt;Kubernetes使用中发现的问题和错误&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#instructions&quot;&gt;Creating a single control-plane cluster with kubeadm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.alexellis.io/kubernetes-in-10-minutes/&quot;&gt;Kubernetes on bare-metal in 10 minutes&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;按照第一篇文章「木子甘」，先进行了系统的设置&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;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;net.bridge.bridge-nf-call-ip6tables =1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;net.bridge.bridge-nf-call-iptables =1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;net.ipv4.ip_forward = 1&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/sysctl.conf&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;sysctl &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;swapoff &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ri&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/swap/s@(.*)@#/&amp;amp;@g&quot;&lt;/span&gt; /etc/fstab&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SELINUX=disabled&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/selinux/config
&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;k8s&lt;/code&gt;的主要程序。&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;apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; apt-transport-https curl &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg |apt-key add -  &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;/etc/apt/sources.list.d/kubernetes.list  &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
apt update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;之后就可以固定住他们的版本了，这样能保证稳定性。&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;apt-mark hold kubelet kubeadm kubectl docker-ce
&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;docker&lt;/code&gt;的镜像：&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;nv&quot;&gt;IMAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;kube-apiserver:v1.15.2 kube-controller-manager:v1.15.2 kube-scheduler:v1.15.2 kube-proxy:v1.15.2 pause:3.1 etcd:3.3.10 coredns:1.3.1&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;imageName &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IMAGE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/&lt;span class=&quot;nv&quot;&gt;$imageName&lt;/span&gt;
    
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/&lt;span class=&quot;nv&quot;&gt;$imageName&lt;/span&gt; k8s.gcr.io/&lt;span class=&quot;nv&quot;&gt;$imageName&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&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;k8s&lt;/code&gt;的名字。注意版本要按照刚刚安装的版本一样，之后就可以开始配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k8s&lt;/code&gt;了。&lt;/p&gt;

&lt;p&gt;然后就可以通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubeadm&lt;/code&gt;进行初始化了。这里设置了内网的ip，还有api服务器的ip。&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;kubeadm init &lt;span class=&quot;nt&quot;&gt;--pod-network-cidr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10.0.1.0/16 &lt;span class=&quot;nt&quot;&gt;--apiserver-advertise-address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10.0.1.&lt;span class=&quot;k&quot;&gt;***&lt;/span&gt;
&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;k8s&lt;/code&gt;就算成功运行了。&lt;/p&gt;

&lt;h3 id=&quot;配置账号&quot;&gt;配置账号&lt;/h3&gt;
&lt;p&gt;如果运行成功，他会提示你配置一下你的账号。要不然不能管理服务。按照提示输入就好了。&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;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.kube
&lt;span class=&quot;nb&quot;&gt;sudo cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; /etc/kubernetes/admin.conf &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.kube/config
&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.kube/config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;配置网络&quot;&gt;配置网络&lt;/h3&gt;
&lt;p&gt;在这&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k8s&lt;/code&gt;成功运行但是他还没准备好。因为网络策略还没配置。详细的配置程序在&lt;a href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/addons/&quot;&gt;官方文档&lt;/a&gt;有很详细的说明。我挑选了&lt;a href=&quot;https://docs.projectcalico.org/v3.8/getting-started/kubernetes/&quot;&gt;calico&lt;/a&gt;。&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;kubectl apply &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; https://docs.projectcalico.org/v3.8/manifests/calico.yaml
&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;k8s&lt;/code&gt;就算准备好了。但是它默认禁止了主节点不会运行其他的程序，所以我们要先把那个去掉&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;kubectl get no &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; yaml | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;taint &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; 5
kubectl taint nodes &lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt; node-role.kubernetes.io/master-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样就大功告成了&lt;/p&gt;

&lt;h2 id=&quot;helm&quot;&gt;Helm&lt;/h2&gt;
&lt;p&gt;参考了这位大大写的&lt;a href=&quot;https://www.jianshu.com/p/d0cdbb49569b&quot;&gt;kunernets使用helm安装tiller踩坑&lt;/a&gt;。真的解决了我的问题。
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Helm&lt;/code&gt;安装很简单，直接从github上的release会有各个版本的编译文件。直接下载下来放在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt;就好。
之后就可以进行配置了。首先，如果打开了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k8s&lt;/code&gt;的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rbac&lt;/code&gt;，那么我们得先建立一个账号。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ymal&quot;&gt;apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;写入到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rbac-config.yaml&lt;/code&gt;就可以用命令导入账号了。&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;nv&quot;&gt;$ &lt;/span&gt;kubectl create &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rbac-config.yaml
serviceaccount &lt;span class=&quot;s2&quot;&gt;&quot;tiller&quot;&lt;/span&gt; created
clusterrolebinding &lt;span class=&quot;s2&quot;&gt;&quot;tiller&quot;&lt;/span&gt; created
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;helm init &lt;span class=&quot;nt&quot;&gt;--service-account&lt;/span&gt; tiller &lt;span class=&quot;nt&quot;&gt;--history-max&lt;/span&gt; 200
&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;tiller&lt;/code&gt;的镜像。我在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker hub&lt;/code&gt;上面找到了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doublemine/kubernetes-helm.tiller&lt;/code&gt;的镜像。
然后可以参照这个&lt;a href=&quot;https://whmzsu.github.io/helm-doc-zh-cn/quickstart/tiller_ssl-zh_cn.html&quot;&gt;文档&lt;/a&gt;来签名。然后带上一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;helm&lt;/code&gt;的源就可以开始配置了。我们还是选择阿里云的源。&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;helm init &lt;span class=&quot;nt&quot;&gt;--debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--tiller-tls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--tiller-tls-cert&lt;/span&gt; ./tiller.cert.pem &lt;span class=&quot;nt&quot;&gt;--tiller-tls-key&lt;/span&gt; ./tiller.key.pem &lt;span class=&quot;nt&quot;&gt;--tiller-tls-verify&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--tls-ca-cert&lt;/span&gt; ca.cert.pem &lt;span class=&quot;nt&quot;&gt;--tiller-image&lt;/span&gt; doublemine/kubernetes-helm.tiller:v2.14.3 &lt;span class=&quot;nt&quot;&gt;--stable-repo-url&lt;/span&gt; https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts &lt;span class=&quot;nt&quot;&gt;--service-account&lt;/span&gt; tiller
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里安装就完成了。&lt;/p&gt;

&lt;p&gt;其他可能有用的&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://my.oschina.net/kikro/blog/3039635&quot;&gt;构建单节点的master的k8s应用 集成helm管理(参考了一些其他大神的资料)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.csdn.net/aixiaoyang168/article/details/81057101&quot;&gt;Kubernetes 集群使用 Helm 搭建 GitLab 并配置 Ingress&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Spilt traffic using route table in mac</title>
   <link href="https://www.mai1015.com//linux/2019/08/11/route-table-to-vpn/"/>
   <updated>2019-08-11T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//linux/2019/08/11/route-table-to-vpn</id>
   <content type="html">&lt;p&gt;When working remotely, we need to access internal resource. Due to security concern, that they are often restricted to only access from local. Then, we need to connect to vpn that enable us to interact with internal server.&lt;/p&gt;

&lt;p&gt;However, we do not want to send all the request over vpn, since it might be slow. How do we control how traffic over vpn?&lt;/p&gt;

&lt;p&gt;This can be achive by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;route&lt;/code&gt; command.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Connect to the vpn, uncheck &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send all traffic over VPN connection&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Delete route to vpn by default. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo route delete -net default -interface ppp0&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Add route to physical interface. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo route add -net 0.0.0.0 -interface en0&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Add ip range route to vpn. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo route add -net 10.0.1.0 -netmask 255.255.255.0 -interface ppp0&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then you are done, and only this ip with in the range will send via vpn.
Source: &lt;a href=&quot;https://superuser.com/questions/1108277/route-only-certain-ip-range-with-vpn-connection&quot;&gt;link&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Install Oracle Java from source</title>
   <link href="https://www.mai1015.com//java/2019/06/20/install-java-from-source/"/>
   <updated>2019-06-20T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//java/2019/06/20/install-java-from-source</id>
   <content type="html">&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;I am using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jhipster&lt;/code&gt; to generate spring boot project. It compile but it does not work well. The first thing is that some function is not compatible. Also, hibernate insert data twice that cause &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConstraintViolationException&lt;/code&gt;. I had post a &lt;a href=&quot;https://github.com/jhipster/generator-jhipster/issues/9914&quot;&gt;Issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It works well on Java 8, so I have to install one more version. However, I cannot install via PPA. It is because webupd8 has &lt;a href=&quot;https://launchpad.net/~webupd8team/+archive/ubuntu/java&quot;&gt;DISCONTINUED&lt;/a&gt; since we need to login to download. So, I have to download java manually. I can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update-alternatives&lt;/code&gt; to switch version.&lt;/p&gt;

&lt;h2 id=&quot;install&quot;&gt;Install&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;Download 1.8 jdk from &lt;a href=&quot;https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&quot;&gt;Oracle&lt;/a&gt;. Register an account and then download. It is better to download &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk-8u211-linux-x64.tar.gz&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp&lt;/code&gt; upload the file to server.&lt;/li&gt;
  &lt;li&gt;unzip the file at server with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tar xzvf filename&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Move the folder into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/jvm/&lt;/code&gt; (The location my java 11 was installed).&lt;/li&gt;
  &lt;li&gt;Then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update-alternatives&lt;/code&gt; with commands.
    &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;update-alternatives &lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt; /usr/bin/java java /usr/lib/jvm/java-8-oracle-amd64/bin/java 100
update-alternatives &lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt; /usr/bin/javac javac /usr/lib/jvm/java-8-oracle-amd64/bin/javac 100
update-alternatives &lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt; /usr/bin/jar jar /usr/lib/jvm/java-8-oracle-amd64/bin/jar 100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Update command to specify version.
    &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;update-alternatives &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; java
update-alternatives &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; javac
update-alternatives &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java&lt;/code&gt; version if it works.&lt;/li&gt;
  &lt;li&gt;write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$JAVA_HOME&lt;/code&gt; to specify location.
I write it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/jvm/default-java&lt;/code&gt; and link to directory with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ln&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then when you switch version, you just change the link to specify version. Inspired by &lt;a href=&quot;https://tecadmin.net/switch-between-java-versions-on-debian/&quot;&gt;Rahul&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>cUrl Test in local</title>
   <link href="https://www.mai1015.com//note/2019/06/12/curl-test-in-local/"/>
   <updated>2019-06-12T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2019/06/12/curl-test-in-local</id>
   <content type="html">&lt;p&gt;So, when we try to access our local development website, we tend to access the website via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8080/&lt;/code&gt;. However, when we need to test for domain name functionality, we need to manually resolve it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hosts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With cURL, we can easily resolve the domain manually. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--resolve HOST:PORT:ADDRESS  Force resolve of HOST:PORT to ADDRESS&lt;/code&gt;, we can change the address of the host.&lt;/p&gt;

&lt;div class=&quot;language-sh 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;c&quot;&gt;# access http&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;--resolve&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'mai1015.com:80:127.0.0.1'&lt;/span&gt; http://mai1015.com/path
&lt;span class=&quot;c&quot;&gt;# access http&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;--resolve&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'mai1015.com:443:127.0.0.1'&lt;/span&gt; https://mai1015.com/path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, the port is included in part of the resolve.&lt;/p&gt;

&lt;p&gt;Or we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-H, --header LINE   Pass custom header LINE to server (H)&lt;/code&gt; to hack the header. We can change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt; in the header. And, the server assumes it is accessing the specified server.&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Host: mai1015.com'&lt;/span&gt; http://127.0.0.1/something
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, it does not work in https because the certificate domain does not match the URL. It is better to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--resolve&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://stackoverflow.com/questions/3390549/set-curl-to-use-local-virtual-hosts&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Javascript open new Window blocked when asynchronous</title>
   <link href="https://www.mai1015.com//javascript/2019/05/23/javascript-window-open-async/"/>
   <updated>2019-05-23T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//javascript/2019/05/23/javascript-window-open-async</id>
   <content type="html">&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;
&lt;p&gt;When you trying to open a new tag for your user. It is ok if we just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window.open&lt;/code&gt; right away. However, we need to do complex task like making request from server to generate the link. Then it will be block by the browser.&lt;/p&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;The solution is pretty straight forward. You can open new tab and modify it after you get the link. This is the sample code below.&lt;/p&gt;

&lt;div class=&quot;language-js 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;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// create new window&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;_blank&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// fetch url&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// then modify the location&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The reason of that is the tab should be open during that user click event loop. Otherwise, it is going to assume that is a pop-up that should be blocked. That is why you can get ad pop-up on some site when you click.&lt;/p&gt;

&lt;p&gt;This is from &lt;a href=&quot;https://stackoverflow.com/questions/19026162/javascript-window-open-from-callback&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Vuex Error With TypeScript</title>
   <link href="https://www.mai1015.com//typescript/2019/05/18/vuex-error-with-ts/"/>
   <updated>2019-05-18T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//typescript/2019/05/18/vuex-error-with-ts</id>
   <content type="html">&lt;p&gt;Vuex is a cool library for vue that allow the project to control state easier. However, I was trying to use it with typescript. It causes error like this. I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;championswimmer/vuex-module-decorators&lt;/code&gt; library to support vuex annotation.&lt;/p&gt;

&lt;div class=&quot;language-js 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;nx&quot;&gt;ERR_ACTION_ACCESS_UNDEFINED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Are&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;you&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;trying&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;access&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;someMutation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;someGetter&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inside&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;That&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;works&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dynamic&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;modules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;If&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dynamic&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mutationName&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;getterName&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Could&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;login&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;///./node_modules/vuex-module-decorators/dist/esm/index.js:311:33)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;///./node_modules/vuex-module-decorators/dist/esm/index.js:96:23)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;///./node_modules/vuex-module-decorators/dist/esm/index.js:77:53)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rejected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webpack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;///./node_modules/vuex-module-decorators/dist/esm/index.js:68:65)&lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I dont understand why it happends because I did not acess any mutation or getter. I was confused. So, I modify my code again and again to see whats wrong. I return a Promise in action and I rejected it. And it cause the same error. So, I search it on google. It turns out that is an &lt;a href=&quot;https://github.com/championswimmer/vuex-module-decorators/issues/26&quot;&gt;issue&lt;/a&gt;. The library warps the error, so the error is confusing. All I did then is add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rawError&lt;/code&gt; option to the annatation so it becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Action({rawError: true})&lt;/code&gt;. And it display error normally.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Useful Git commands and Clone local</title>
   <link href="https://www.mai1015.com//git/2019/05/18/git-clone-local-file/"/>
   <updated>2019-05-18T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//git/2019/05/18/git-clone-local-file</id>
   <content type="html">&lt;p&gt;Git is a strong version controll system. It allows you to track code and verison, and keep all the data you need to go back to certain version.&lt;/p&gt;

&lt;p&gt;This is so good that we can use it even if we are working solo. We can see how the project grows. So, this is how to setup a project locally.&lt;/p&gt;

&lt;h2 id=&quot;steps&quot;&gt;Steps&lt;/h2&gt;
&lt;p&gt;Here are some steps to prepare you own repository.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you will need to create a project by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd /path/to/project/&lt;/code&gt;. Then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt; to init a new git repository.&lt;/li&gt;
  &lt;li&gt;Then you will need to add your project files. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add .&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Finally &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m &quot;Inital&quot;&lt;/code&gt; to commit you first changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, those step setup the basics. As you go futher, you will get more files in your project. Remember to add and commit it as you go.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Adding file to git: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add file&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Commit: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m &quot;message&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you only change some file, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -am &quot;message&quot;&lt;/code&gt; to make a fast commit. It saves all your time to add files that changes.&lt;/p&gt;

&lt;p&gt;If you want to make it easier to share, you can init a bare repository &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init --bare /path&lt;/code&gt;. This does not really contain your work file as usual. You have to clone and commit it if you want to modify the file.&lt;/p&gt;

&lt;h2 id=&quot;clone&quot;&gt;Clone&lt;/h2&gt;
&lt;p&gt;If we want to get codes from other, we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone git://...&lt;/code&gt; to clone other repository. and we can even clone our repository like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone /path/to/project/ /path&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, you might say, why would you do it. It is because you want to keep an deployment copy else where that does not change a lot.&lt;/p&gt;

&lt;h2 id=&quot;update&quot;&gt;Update&lt;/h2&gt;
&lt;p&gt;You got your copy of code, but you want to keep it up to date if you working with others. The command is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;simple-deployment&quot;&gt;Simple Deployment&lt;/h2&gt;
&lt;p&gt;So you are done with you coding. Now, you want to deploy you code, you can try this &lt;a href=&quot;https://gist.github.com/noelboss/3fe13927025b89757f8fb12e9066f2fa&quot;&gt;gist&lt;/a&gt;. Add hooks that runs every commit.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nginx reverse proxy solve no avaliable</title>
   <link href="https://www.mai1015.com//nginx/2019/05/14/nginx-reverse-proxy-no-avaliable/"/>
   <updated>2019-05-14T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//nginx/2019/05/14/nginx-reverse-proxy-no-avaliable</id>
   <content type="html">&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;We use a main server reverse proxy all the request to other backend server. So, it means that the client access the main server, and nginx reverse proxy the request to the other serever.
&lt;img src=&quot;https://www.cloudflare.com/img/learning/cdn/glossary/reverse-proxy/reverse-proxy-flow.svg&quot; alt=&quot;reverse proxy&quot; /&gt;
So, we use subdomain to dynamically resolve the address so it is working well when server ip changes.&lt;/p&gt;

&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;
&lt;p&gt;Today, the nginx is not working as expected. It redirect all request to 502 page. And we found the error log.&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;2019/05/14 08:41:15 [error] 688#688: *4 connect() failed (110: Connection timed out) while connecting to upstream, client: 113.*.*.*, server: furry.top, request: &quot;GET / HTTP/2.0&quot;, upstream: &quot;https://116.*.*.*:443/&quot;, host: &quot;furry.top&quot;, referrer: &quot;https://furry.top/&quot;
2019/05/14 08:41:15 [error] 688#688: *4 no live upstreams while connecting to upstream, client: 113.*.*.*, server: furry.top, request: &quot;GET / HTTP/2.0&quot;, upstream: &quot;https://https/&quot;, host: &quot;furry.top&quot;, referrer: &quot;https://furry.top/&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It is quite weird because when we reload the server it starts working. And then stop working after 10 seconds. We could not found why this happend.&lt;/p&gt;

&lt;h2 id=&quot;attempts&quot;&gt;Attempts&lt;/h2&gt;
&lt;p&gt;I assume that it is because of the unstable connection. So, I check append &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_fails=0&lt;/code&gt; config to ensure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upstream&lt;/code&gt; does not fail. However, it gets worse. Nginx basically try to connect to backend continuously and not reply to any connection. However, when I &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; backend address, it has successfully responsed. So nothing wrong with the connection but nginx some how cannot connect to the backend.&lt;/p&gt;

&lt;p&gt;I have no idea why it happend. Then I check the connection with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netstat -ap&lt;/code&gt;. One line draw my attention.&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;Proto Recv-Q Send-Q Local Address        Foreign Address   State     PID/Program name
tcp        0      1 main-server.a:36298  166.*.*.*:http    SYN_SENT  10128/nginx: worker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Since there is no respond from the address, it did not connect to correct backend address. But, why it only works for small period of time? Does it mean that the dns server did not work?&lt;/p&gt;

&lt;p&gt;So I check in the configuration file again. I found &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolver 114.114.114.114&lt;/code&gt;, this changes the DNS server. So, to verify the address. I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig&lt;/code&gt; command, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig @114.114.114.114 furry.top&lt;/code&gt; and the result is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;114.114.114.114&lt;/code&gt; is not working. So, I replace the DNS with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8.8.8.8&lt;/code&gt; and the problem solved.&lt;/p&gt;

&lt;p&gt;So, that’s why nginx fail to connect to backend but I cannot find any log indicate that the DNS failed. It is because I did not check the default logging file.&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;[error] 2439#2439: upstream-dynamic-servers: 'furry.top' could not be resolved (110: Operation timed out)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The answer was there.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Keycloak Docker setup and reverse proxy from nginx</title>
   <link href="https://www.mai1015.com//development/2019/05/05/docker-keycloak-proxy-behind-nginx/"/>
   <updated>2019-05-05T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//development/2019/05/05/docker-keycloak-proxy-behind-nginx</id>
   <content type="html">&lt;p&gt;Keycloak is an open source Identity and Access Management software that is part of Red Hat project. It provided OAuth and SSO support for your application and software. It is easy to set up, but you need to download the dependency and set up in the configuration file. We can use Docker to set this up easily.&lt;/p&gt;

&lt;p&gt;From &lt;a href=&quot;https://github.com/jboss-dockerfiles/keycloak&quot;&gt;github&lt;/a&gt; repository, we can find the information about Keycloak for Docker. One of the simple setups is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run -e KEYCLOAK_USER=&amp;lt;USERNAME&amp;gt; -e KEYCLOAK_PASSWORD=&amp;lt;PASSWORD&amp;gt; jboss/keycloak&lt;/code&gt;. Then it is going up and running. We can have a database connection when we set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DB_VENDOR&lt;/code&gt; environment variable. There is a sample setup for Keycloak with MySQL. It is pretty easy with docker.&lt;/p&gt;

&lt;p&gt;However, I do not need multiple MySQL instances running. I prefer a single MySQL service at my localhost. So, we need to connect host MySQL within the container. We have to locate the host IP address from the container. Docker used to provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host.docker.internal&lt;/code&gt; to resolve the host IP address. However, it resolves to nothing in Ubuntu docker. I found a simple workaround from &lt;a href=&quot;https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;SETUP&lt;/h2&gt;
&lt;p&gt;Basically, it set the network mode to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt;, so localhost can access the actual machine. so I set it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;network_mode: host&lt;/code&gt;. So the sample &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compose&lt;/code&gt; setup will look like this. With the file, we can set the database clear. The file is generated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jhipster&lt;/code&gt;, and I modify it to connect it to the database.&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;2'&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;keycloak&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;jboss/keycloak:5.0.0&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;host&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-b&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;0.0.0.0&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dkeycloak.migration.action=import&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dkeycloak.migration.provider=dir&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dkeycloak.migration.dir=/opt/jboss/keycloak/realm-config&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dkeycloak.migration.strategy=OVERWRITE_EXISTING&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Djboss.socket.binding.port-offset=1000&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./realm-config:/opt/jboss/keycloak/realm-config&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PROXY_ADDRESS_FORWARDING=true&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;KEYCLOAK_USER=admin&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;KEYCLOAK_PASSWORD=admin&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DB_VENDOR=mariadb&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DB_DATABASE=keycloak&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DB_USER=keycloak&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DB_PASSWORD=passwd&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;9080:9080&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;9443:9443&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;10990:10990&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It is important to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROXY_ADDRESS_FORWARDING=true&lt;/code&gt; since we want to working with reverse proxy nginx.&lt;/p&gt;

&lt;p&gt;We can then run the file with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose -f keycloak.yml up&lt;/code&gt;. However, it does not work because of the message &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Failed to start service org.wildfly.network.interface.private&lt;/code&gt;. There is nothing I can find on the internet, but it works fine on my other computer. It should be a problem with docker in Ubuntu. So, I have used another way. Please comment if you anything related to the issue.&lt;/p&gt;

&lt;h2 id=&quot;mysql&quot;&gt;MYSQL&lt;/h2&gt;
&lt;p&gt;We have to know the IP address of the host in the container. So, I found this command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip route show | awk '/default/ {print $3}'&lt;/code&gt;. It will show the host IP in the docker. We can simply do it like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run --rm alpine ip route show | awk '/default/ {print $3}'&lt;/code&gt;, and we will see the IP in terminal. For me, the IP is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;172.17.0.1&lt;/code&gt;. So I add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DB_ADDR=172.17.0.1&lt;/code&gt; into the environment. And let myself listen to IP address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.0.0.0&lt;/code&gt; then the container is allowed to connect to the service.&lt;/p&gt;

&lt;p&gt;One more thing is the MySQL user. We can add a user with remote access, but it is not safe. So I add the user in MySQL with SQL command.&lt;/p&gt;

&lt;div class=&quot;language-sql 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;k&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;USER&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'keycloak'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'172.*'&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDENTIFIED&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;GRANT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ALL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIVILEGES&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`keycloak`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;TO&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'keycloak'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'172.*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;FLUSH&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;PRIVILEGES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;or we can simply do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRANT ALL PRIVILEGES ON &lt;/code&gt;keycloak&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.* To 'keycloak'@'172.*' IDENTIFIED BY 'password';&lt;/code&gt;. They both work well with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mariadb-10.3.14&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;nginx&quot;&gt;NGINX&lt;/h2&gt;
&lt;p&gt;We want to proxy it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt; so we do not need to convert certificate. It is easier to replace and do not stop the keycloak service. So, I obtain a certificate with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot&lt;/code&gt; and activate it with Nginx configuration like this.&lt;/p&gt;

&lt;h3 id=&quot;nginx-host-configuration&quot;&gt;nginx host configuration&lt;/h3&gt;
&lt;div class=&quot;language-nginx 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;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;rewrite&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://example.com&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$request_uri&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;permanent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# managed by Certbot&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;access_log&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/log/nginx/ide.mai1015.com-access.log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;error_log&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/log/nginx/ide.mai1015.com-error.log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# SSL configuration&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# listen [::]:443 ssl http2 ipv6only=on;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Note: You should disable gzip for SSL traffic.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# See: https://bugs.debian.org/773332&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Read up on ssl_ciphers to ensure a secure configuration.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# See: https://bugs.debian.org/765782&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Self signed certs generated by the ssl-cert package&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Don't use them in a production server!&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# include snippets/snakeoil.conf;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Add index.php to the list if you are using PHP&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.html&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.htm&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.nginx-debian.html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://localhost:9080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_read_timeout&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# proxy header&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Real-IP&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$remote_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Forwarded-For&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Scheme&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Host&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# ws&lt;/span&gt;
        &lt;span class=&quot;kn&quot;&gt;proxy_http_version&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;#proxy_set_header Upgrade $http_upgrade;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;#proxy_set_header Connection 'Upgrade';&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# proxy_cache_bypass $http_upgrade;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;#proxy_redirect http://localhost:9080 https://example.com;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;ssl_certificate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# managed by Certbot&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# managed by Certbot&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So those configurations are important to allow keycloak to work correctly. Without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Host&lt;/code&gt; header will break the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redirect_url&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-nginx 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;k&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Real-IP&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$remote_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Forwarded-For&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Scheme&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Host&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So we have a fully configurated keycloak working behind reverse proxy Nginx.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ansible Automation for Server Deploy and Test</title>
   <link href="https://www.mai1015.com//development/2019/05/01/Ansible-Automation-for-server-deploy-and-test/"/>
   <updated>2019-05-01T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//development/2019/05/01/Ansible-Automation-for-server-deploy-and-test</id>
   <content type="html">&lt;p&gt;When talking about deploying a server, it is a pain to configure servers by hand. You have to type in commands line by line. Then edit the config file to make sure that works. If you need to configure all the time, it wastes a lot of time struggle and waits for server.&lt;/p&gt;

&lt;p&gt;Then I look for a way to automate this process. I found a lot of program like chef, puppet, ansible, saltstack, terraform, cloudformation, etc. They are different but they serve one purpose, deploy servers for you.&lt;/p&gt;

&lt;p&gt;First, I tried chef. It is cool, clear syntax, fast. I can always check if the setup was correct by config rules. However, after some day of experience, I give up. It has so many stuff to use, I have to keep search and try it out. If I am managing a lot of servers, I will definitely use it.&lt;/p&gt;

&lt;p&gt;Then I found ansible. It is pretty easy to learn, the configuration file is using YMAL. One of the samples from documents.&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;webservers&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;http_port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;max_clients&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;200&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;remote_user&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;root&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ensure apache is at the latest version&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;httpd&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;latest&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write the apache config file&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/srv/httpd.j2&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/etc/httpd.conf&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;notify&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;restart apache&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ensure apache is running&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;httpd&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;started&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;restart apache&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;httpd&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;restarted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is easy to both read and writes. It enables you to config server via ssh using ansible in your computer.&lt;/p&gt;

&lt;p&gt;I learn a few, so I will take some example and show how ansible works and automate the process.&lt;/p&gt;

&lt;p&gt;After the &lt;a href=&quot;https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#intro-installation-guide&quot;&gt;installation&lt;/a&gt; guide, you will configure the host that you want to config in groups. We create the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/ansible/hosts&lt;/code&gt; to declare individual servers or server group.&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;192.0.2.50

[group]
aserver.example.org
bserver.example.org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or if you want to move the file location, you can create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ansible.cfg &lt;/code&gt; and put in the following content. It specifies the location of the host file.&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;[defaults]
inventory = /path/to/hosts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we can start with a playbook. A playbook is the configuration file that contains what servers to deploy and the tasks to do. We can start with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt; installation.&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;nn&quot;&gt;---&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ide source&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;local&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;install nginx&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;apt&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;nginx'&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;update_cache&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This file will try to config all the server under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;local&lt;/code&gt; group and then use apt to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt; to latest version after updated the cache. It is pretty clear. Or we can install multiple packages.&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Install common&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;apt&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;git'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gdb'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;build-essential'&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;update_cache&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;install_recommends&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that, we can make sure that nginx is started.&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;restart NGINX&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nginx&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;started&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, that’s all the basic function that ansible able to do easily. It also works with loop, I can install a list of item of go with. I have to add environment variable so I just activate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.profile&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;install go ext&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become_user&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/.profile&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;go&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;with_items&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/stamblerre/gocode&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/uudashr/gopkgs/cmd/gopkgs&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/ramya-rao-a/go-outline&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/acroca/go-symbols&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;golang.org/x/tools/cmd/guru&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;golang.org/x/tools/cmd/gorename&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/rogpeppe/godef&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/zmb3/gogetdoc&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/sqs/goreturns&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;golang.org/x/tools/cmd/goimports&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;golang.org/x/lint/golint&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/alecthomas/gometalinter&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;honnef.co/go/tools/...&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/golangci/golangci-lint/cmd/golangci-lint&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/mgechev/revive&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;golang.org/x/tools/cmd/gopls&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;github.com/go-delve/delve/cmd/dlv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;They are all useful and easy to maintain config.&lt;/p&gt;

&lt;p&gt;And it provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt; that allow reusable playbook. Then I just need to write&lt;/p&gt;

&lt;div class=&quot;language-yaml 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;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ide source&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ideserv&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;yes&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ide&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;web&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ansible-playbook coder.yml&lt;/code&gt; and it will try to log in and do all the stuff for me.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows Subsystem Linux Development</title>
   <link href="https://www.mai1015.com//development/2019/04/19/windows-subsystem-linux-dev/"/>
   <updated>2019-04-19T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//development/2019/04/19/windows-subsystem-linux-dev</id>
   <content type="html">&lt;p&gt;Linux SHELL is very useful in development. It is color coded, easier to manage, and more command. Windows provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WSL&lt;/code&gt; to enable linux system in windows. To enable it this is the &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/wsl/install-win10&quot;&gt;official guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically, you need to enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows Subsystem for Linux&lt;/code&gt; in the program &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;windows fratures&lt;/code&gt;. Then select one of the linux system in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Microsoft Store&lt;/code&gt;. The one I recommand is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Debian&lt;/code&gt;. It is small and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ubuntu&lt;/code&gt; is base on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Debian&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After you restart and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Debian&lt;/code&gt;, linux will be ready to go. You now running full operational linux in windows. And it can access windows directories.&lt;/p&gt;

&lt;p&gt;Installation will be easier. For git, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt install git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I try to let IDE (Intellij IDEA) to run git through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl&lt;/code&gt;, I found a bat file from &lt;a href=&quot;https://stackoverflow.com/questions/43666009/using-git-in-windows-subsystem-for-linux-through-intellij&quot;&gt;here&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;@echo off
setlocal enabledelayedexpansion
set command=%*
set find=C:\Users\%USERNAME%\AppData\Local\Temp\git-commit-msg-.txt
set replace=/mnt/c/Users/%USERNAME%/AppData/Local/Temp/git-commit-msg-.txt
call set command=%%command:!find!=!replace!%%
echo | C:\Windows\Sysnative\bash.exe -c 'git %command%'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It works beautifully.&lt;/p&gt;

&lt;p&gt;This is far from a good development. Since there are more to install. And I install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java&lt;/code&gt; in windows, so I can use it eaiser without running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl java&lt;/code&gt; all the time.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Centos install newer package of gcc via yum</title>
   <link href="https://www.mai1015.com//notes/2019/04/09/Centos-install-newer-package-of-gcc/"/>
   <updated>2019-04-09T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//notes/2019/04/09/Centos-install-newer-package-of-gcc</id>
   <content type="html">&lt;p&gt;Centos is popular for it is stability and security. It meets all kinds of purpose for commercial requirements. However, to maintain security and stability, most of its package are outdated. It is harder to run newer version compiled program with lower version of gcc.&lt;/p&gt;

&lt;p&gt;We can solve this easily by compiler new version of gcc. It is not that hard, but requires some time to do the job. We can fix it in a easy way. Thanks to &lt;em&gt;Software Colletions&lt;/em&gt;, it is provide in RHSCL(Red Hat Software Collections) in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devtoolset-7&lt;/code&gt;. We just simply need to enable it and download it from the repository. It can be done in following steps. You can find more information &lt;a href=&quot;https://www.softwarecollections.org/en/scls/rhscl/devtoolset-7/&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;centos-release-scl&lt;/code&gt; in centos repository
    &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;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;centos-release-scl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Enable RHSCL repository
    &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;yum-config-manager &lt;span class=&quot;nt&quot;&gt;--enable&lt;/span&gt; rhel-server-rhscl-7-rpms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Install the collections
    &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;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;devtoolset-7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Enable the package
    &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;scl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;devtoolset-7 bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find more other package from the &lt;a href=&quot;https://www.softwarecollections.org/en/scls/user/rhscl/&quot;&gt;website&lt;/a&gt;. I can also download &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt; from &lt;a href=&quot;https://www.softwarecollections.org/en/scls/rhscl/rh-nodejs10/&quot;&gt;here&lt;/a&gt;. So we do not need to spend time compile the software.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Scrapy grap files from website</title>
   <link href="https://www.mai1015.com//notes/2019/04/05/Scrapy-grap-files-from-website/"/>
   <updated>2019-04-05T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//notes/2019/04/05/Scrapy-grap-files-from-website</id>
   <content type="html">&lt;p&gt;I am trying to download some material from my course website. However, there are a lot of files in the server. I do not want to download file one by one. So, I try to write a script that can help me download all the files at once.&lt;/p&gt;

&lt;p&gt;I found &lt;a href=&quot;https://scrapy.org/&quot;&gt;scrapy&lt;/a&gt;. It is a crawler framework that can extract data from website.&lt;/p&gt;

&lt;p&gt;First of all, install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrapy&lt;/code&gt; from source. In my case, I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt;. It is simlar fo pip but I can setup different envirnment with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda&lt;/code&gt;. Installtion command is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda install -c conda-forge scrapy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After install we can follow this &lt;a href=&quot;http://doc.scrapy.org/en/latest/intro/install.html&quot;&gt;guide&lt;/a&gt;. First, I create the project with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrapy startproject yorku&lt;/code&gt; that creates an sample configurated scrapy project.
It looks like&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;scrapy/
   ├── yorku/
   │    ├── __init__.py
   │    ├── items.py
   │    ├── middlewares.py
   │    ├── pipelines.py
   │    ├── settings.py
   │    └── spiders/
   │        └── __init__.py
   └── scrapy.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It contains only basic file for setting up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spider&lt;/code&gt;, we can generate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spider&lt;/code&gt; with command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrapy genspider &amp;lt;name&amp;gt; &amp;lt;domain name&amp;gt;&lt;/code&gt;. I typed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrapy genspider wikieecs wiki.eecs.yorku.ca&lt;/code&gt; that generates the spider that starts like this.&lt;/p&gt;

&lt;div class=&quot;language-py 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scrapy&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;re&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scrapy.utils.python&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_native_str&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WikieecsSpider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scrapy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Spider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'wikieecs'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;allowed_domains&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'wiki.eecs.yorku.ca'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_urls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'http://wiki.eecs.yorku.ca/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can write logic to seek the links to the file. So, it will start access the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;starts_urls&lt;/code&gt;. When it finish loading the page, it will pass the page in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;response&lt;/code&gt; object to parse function. So, we can extract the link of the files from the page. It can be done easily with build in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css seceltor&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xpath&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-py 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;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'a::attr(href)'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# select all the link with url.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It returns an array of object. Then we can use loop to see all the links and select the files.&lt;/p&gt;

&lt;div class=&quot;language-py 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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'a::attr(href)'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# get the link from element
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.pdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# if it is an pdf
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;follow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# instrcut scrapy to download the file
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So this function will generate a new array that conatains all the function. If you want to download multiple file with different ext. i.e. docx, pptx. You can type all stuff in to an array like this.&lt;/p&gt;

&lt;div class=&quot;language-py 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;ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'.pdf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.ppt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.pptx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.doc'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.docx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.v'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.c'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.tar'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.tar.gz'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.zip'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# if it ends with any of the ext
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So you can download specified list of files. Then we need to generate a new callback &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;save_file&lt;/code&gt; to save the file.&lt;/p&gt;

&lt;div class=&quot;language-py 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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;save_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# assume the last path of url is the name
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'wb'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# open a new file
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# write content downloaded
&lt;/span&gt;    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Save file %s'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# display the file downloaded
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, our school website require us to login in order to download. And it uses &lt;a href=&quot;https://en.wikipedia.org/wiki/Basic_access_authentication&quot;&gt;basic access authentication&lt;/a&gt;. So we need to generate a new header &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Authorization&lt;/code&gt; if it require us to login. Scrapy support this with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HttpAuthMiddleware&lt;/code&gt; by defaut, we just need to spcify this with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http_user&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http_pass&lt;/code&gt; in the spider.&lt;/p&gt;

&lt;div class=&quot;language-py 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;c1&quot;&gt;# improt omitted
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WikieecsSpider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scrapy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Spider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;http_user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'xxxx'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;http_pass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'xxxx'&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# other definition and functions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then you will have a working spider. The final code will look like.&lt;/p&gt;

&lt;div class=&quot;language-py 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scrapy&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;re&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scrapy.utils.python&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_native_str&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WikieecsSpider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scrapy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Spider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;http_user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'xxxx'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;http_pass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'xxxx'&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'wikieecs'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;allowed_domains&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'wiki.eecs.yorku.ca'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'www.eecs.yorku.ca'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_urls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'https://wiki.eecs.yorku.ca/course_archive/2018-19/W/2011/assignments:start'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'.pdf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.ppt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.pptx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.doc'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.docx'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.v'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.c'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.tar'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.tar.gz'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.zip'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'a::attr(href)'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;follow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;save_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'wb'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Save file %s'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We just need put all the url in to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start_urls&lt;/code&gt; and it will start to scan the files and try to download it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Recurrent Neural Networks</title>
   <link href="https://www.mai1015.com//note/2019/03/15/Recurrent-Neural-Networks/"/>
   <updated>2019-03-15T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2019/03/15/Recurrent-Neural-Networks</id>
   <content type="html">\[\begin{align*}
\frac{\partial\varepsilon}{\partial\theta}&amp;amp;=\sum_{1 \leq t \leq T} \frac{\partial\varepsilon_{t}}{\partial\theta}\\
\frac{\partial\varepsilon}{\partial\theta}&amp;amp;=\sum_{1 \leq k \leq t} (\frac{\partial\varepsilon_{t}}{\partial x_{t}}\frac{\partial x_{t}}{\partial x_{k}}\frac{\partial^{+}x_{k}}{\partial \theta})\\
\frac{\partial x_{t}}{\partial x_{k}}&amp;amp;=\amalg_{t \geq i &amp;gt; k} \frac{\partial x_{i}}{\partial x_{i-1}}=\amalg_{t \geq i &amp;gt; k} W_{rec}^{T} diag(\sigma^{'}(x_{i-1}))
\end{align*}\]

&lt;p&gt;\(W_{rec} \sim small (&amp;lt;1)\) cause vanishing&lt;br /&gt;
\(W_{rec} \sim large (&amp;gt;1)\) cause Exploding&lt;/p&gt;

&lt;h3 id=&quot;solution-to-the-vanishing-gradient-problem&quot;&gt;Solution to The Vanishing Gradient Problem.&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Exploding Gradient
    &lt;ul&gt;
      &lt;li&gt;Trucated Backpropagation&lt;/li&gt;
      &lt;li&gt;Penalties&lt;/li&gt;
      &lt;li&gt;Gradient Clipping&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Vanishing Gradient
    &lt;ul&gt;
      &lt;li&gt;Weight Initialization&lt;/li&gt;
      &lt;li&gt;Echo State Networks&lt;/li&gt;
      &lt;li&gt;Long Short-Term Memory Networks(LSTMs)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lstm&quot;&gt;LSTM&lt;/h3&gt;
&lt;p&gt;Set \(W_{rec}\) to 1.
&lt;a href=&quot;http://colah.github.io/posts/2015-08-Understanding-LSTMs/&quot;&gt;This&lt;/a&gt; is a good post about it. It basically saying that the tradictional neural network is hard to link between the context. However, they are good at linking it long-term. LSTMs is a way to solve it. It basically adds more action before the activation function, and that allows the&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GTX1070 cannot work with Tensorflow</title>
   <link href="https://www.mai1015.com//deeplearning/2019/03/15/GTX1070-Can-not-work-with-Tensorflow/"/>
   <updated>2019-03-15T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//deeplearning/2019/03/15/GTX1070-Can-not-work-with-Tensorflow</id>
   <content type="html">&lt;p&gt;I was trying to set up Deep learning on my Windows PC. However, after installing Anaconda, I cannot use my GPU to do my training. It shows&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;E tensorflow/stream_executor/cuda/cuda_blas.cc:461] failed to run cuBLAS routine cublasSgemm_v2: CUBLAS_STATUS_EXECUTION_FAILED
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I search for many sources trying to solve this problem. I tried to set up with &lt;a href=&quot;https://towardsdatascience.com/tensorflow-gpu-installation-made-easy-use-conda-instead-of-pip-52e5249374bc&quot;&gt;this&lt;/a&gt; guide, and then I found &lt;a href=&quot;https://www.pugetsystems.com/labs/hpc/The-Best-Way-to-Install-TensorFlow-with-GPU-Support-on-Windows-10-Without-Installing-CUDA-1187/&quot;&gt;this&lt;/a&gt; one with detailed. The setup was smooth, but I still cannot run the training because of the error.&lt;/p&gt;

&lt;p&gt;It is definitely a nightmare to solve the issue. Then I found it on &lt;a href=&quot;https://stackoverflow.com/questions/38303974/tensorflow-running-error-with-cublas&quot;&gt;stackoverflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The solution is&lt;/p&gt;
&lt;div class=&quot;language-python 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;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;your&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;under&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tensorflow&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConfigProto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gpu_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;allow_growth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It works well when I modify the config “allow_growth” to true. Then it can use GPU to train the networked lighting fast.&lt;/p&gt;

&lt;p&gt;UPDATE 2019-04-05:
It was working well for some time. However, I found some serious problem with the graphic card. My GTX1070 crash everything if the memory usage exceed 3 GB. I found it when I was playing BF5. Now, I have sent the graphic card to repaired. So, if you run into some problem like this, you should try to check if your graphic card is working in a good condition.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>C Pointer</title>
   <link href="https://www.mai1015.com//note/2019/02/14/C-Special-Pointer/"/>
   <updated>2019-02-14T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2019/02/14/C-Special-Pointer</id>
   <content type="html">&lt;p&gt;C pointer is powerful that can point to anywhere with good definition. Here are collections of interesting way to use pointer.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;definition&lt;/th&gt;
      &lt;th&gt;meaning&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;link&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type *i;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;simple pointer&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;#type-i&quot;&gt;here&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type *i[n];&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;array of n pointer&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;#type-in&quot;&gt;here&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type (*p)[n];&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;a pointer to an array of n&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;#type-pn&quot;&gt;here&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type (*p)();&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;a pointer to function that return type&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;#type-p&quot;&gt;here&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type (*p[n])();&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;a pointer to an array of n functions that return type&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;#type-xn&quot;&gt;here&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;type-i&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type *i&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;language-c 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;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// j == 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;type-in&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type *i[n]&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;language-c 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;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// j == 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;type-pn&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type (*p)[n]&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;language-c 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;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// i = {10,11,?,...,?}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;type-p&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type (*p)()&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;language-c 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;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//result:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//test&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;type-xn&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type (*x[n])()&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&quot;language-c 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;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//result:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//test&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Social Engineering Phishing</title>
   <link href="https://www.mai1015.com//security/2019/02/06/Social-Engineering-Phishing/"/>
   <updated>2019-02-06T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//security/2019/02/06/Social-Engineering-Phishing</id>
   <content type="html">&lt;p&gt;This &lt;a href=&quot;/projects/amazon&quot;&gt;page&lt;/a&gt; is intended to show how I do during a social engineering phishing in EECS3482 at York University. This is not going to record any of the data you put in the form.&lt;/p&gt;

&lt;p&gt;The process is simple, just download the whole page and modify the form. and it is done. It requires some HTML skill to understand how it works.&lt;/p&gt;

&lt;p&gt;This is kind of attack that trick user put their password into a fake login form. And you will see your password in the URL bar in this case. That way, the attacker will record the password and find a chance to steal your account.&lt;/p&gt;

&lt;p&gt;There are many ways to prevent. Simply look closely at the URL. Does it look different or is it SSL protected with a green lock and the name of the company.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Arduino Intergrated Circuit Communication Note</title>
   <link href="https://www.mai1015.com//arduino/2019/02/05/Arduino-Intergrated-Circuit-Communication-Note/"/>
   <updated>2019-02-05T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//arduino/2019/02/05/Arduino-Intergrated-Circuit-Communication-Note</id>
   <content type="html">&lt;p&gt;I am trying to build a step counter with MPU6050, and it is not so hard to do it. I learn a lot of stuff relative to how hardware like arduino and other parts communicating.&lt;/p&gt;

&lt;h2 id=&quot;type-of-communication&quot;&gt;Type of communication&lt;/h2&gt;
&lt;p&gt;I found three common type of communication protocals are widely used:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;I2C (Inter-Integrated Circuit Protocol)&lt;/li&gt;
  &lt;li&gt;UART (Universal Asynchronous Receiver/Transmitter)&lt;/li&gt;
  &lt;li&gt;SPI (Serial Peripheral Interface)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;i2c-inter-integrated-circuit&quot;&gt;I2C (Inter-Integrated Circuit)&lt;/h3&gt;
&lt;p&gt;This protocal is simple to use. It connects all part via &lt;em&gt;I2C Bus&lt;/em&gt; which consist two lines are Serial Data Line (SDA) and Serial Clock Line (SCL).&lt;/p&gt;

&lt;p&gt;A microcontroller act as master and other part act as slave takes controll from the master. The clock is controll by the master. Sameple schematic below, from &lt;a href=&quot;https://en.wikipedia.org/wiki/I²C#Arbitration_using_SDA&quot;&gt;wikipedia&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/image/2019-02-05/1024px-I2C.png&quot; alt=&quot;I2C Sample Schematic&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each device have a unique address so thry can communicate. Basic communication is using transfers of 8 bytes. Each I2C slave have 7 bytes address. The bit 0 is signal to read or write to the device.&lt;/p&gt;

&lt;p&gt;Communication is initialized by master device. In normal state, both lines SCL and SDA are high. Then &lt;em&gt;Start condition&lt;/em&gt; is drop the SDA line. After that, ther master will start sending the address. Then follow by one bit of operation. If bit was 0, it means writing to slave. If bit was 1, then it will read from the slave. Once all bits are finish, it follows the &lt;em&gt;Stop condition&lt;/em&gt;. Then the other device on the bus can use the bus. The image show how the device communicate, image from &lt;a href=&quot;https://i2c.info&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/image/2019-02-05/i2c-protocol.png&quot; alt=&quot;I2C protocal&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;uart-universal-asynchronous-receivertransmitter&quot;&gt;UART (Universal Asynchronous Receiver/Transmitter)&lt;/h3&gt;
&lt;p&gt;This is not really a kind of communication protocol like I2C. It is a standalone IC. It only use two wires (two Tx pin to Rx pin) to transmit data between devices. This transmit data asynchronously, because there is no clock needed. Instead, it adds start and stop bit to the packet (Image below from &lt;a href=&quot;http://www.circuitbasics.com/basics-uart-communication/&quot;&gt;here&lt;/a&gt;). So, it know when to start reading and end reading. They read byte at a specify frequency aka baud rate. Baud rate is the speed of data express in bit pre second (bps).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/image/2019-02-05/Introduction-to-UART-Packet-Frame-and-Bits-2.png&quot; alt=&quot;Uart packet&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It works simple, however, you cannot connect multiple slave or mutiple master systems. Also, we need to adjuest the BPS to match the other part.&lt;/p&gt;

&lt;p&gt;It’s no compatible with the I2C.&lt;/p&gt;

&lt;h3 id=&quot;spi-serial-peripheral-interface&quot;&gt;SPI (Serial Peripheral Interface)&lt;/h3&gt;
&lt;p&gt;I haven research about this. I have little knowledge of it. Thats how arduino and computer communicate. I will do some more research about it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Full page background with css3</title>
   <link href="https://www.mai1015.com//html/2019/01/20/full-page-backgroud-css/"/>
   <updated>2019-01-20T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//html/2019/01/20/full-page-backgroud-css</id>
   <content type="html">&lt;p&gt;I was trying to make a page with a full image background. It was simple. I fit everything into one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; with class container. And give the background to the body tag.&lt;/p&gt;

&lt;div class=&quot;language-css 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;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;url(/image/bg.jpg)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;no-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It works well. However, I tried to make it responsive to different devices. It leaves an ugly white space at the bottom. I can tell that it is because the body did not have a value of height. I have to force it to have the height of the screen. Then, the code becomes:&lt;/p&gt;

&lt;div class=&quot;language-css 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;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;url(/image/bg.jpg)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;no-repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It actually overdoes it. I now have a scroller at the right. This is so confusing for the unexpected result. After researching a little bit. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;margin&lt;/code&gt; value actually pull the body down, so I got a margin for the body at the top.&lt;/p&gt;

&lt;p&gt;There is a simple fix. I just add one more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;div&lt;/code&gt; that warps container, and give it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overflow: auto;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-css 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;nc&quot;&gt;.page&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Define New Conversions for printf</title>
   <link href="https://www.mai1015.com//c/2019/01/07/define-new-conversion-for-printf/"/>
   <updated>2019-01-07T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//c/2019/01/07/define-new-conversion-for-printf</id>
   <content type="html">&lt;p&gt;In GNU C Library, there are ways to &lt;a href=&quot;https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html&quot;&gt;Customizing printf&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It allows you to create conversion specifiers. It allow you to print important data structures of our programe.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>SSH refuse on bad ownership or modes</title>
   <link href="https://www.mai1015.com//linux/2019/01/05/sshd-refuse-on-bad-ownership-or-modes/"/>
   <updated>2019-01-05T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//linux/2019/01/05/sshd-refuse-on-bad-ownership-or-modes</id>
   <content type="html">&lt;p&gt;After I updated the gitlab to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;11.6.1-ee&lt;/code&gt;, ssh to git user failed.&lt;/p&gt;

&lt;p&gt;I went on gitlab and did not found any useful information. Then I start checking my sshd services.&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;Jan  6 06:48:26 UltGeek-GitLabServer sshd[115940]: error: Unsafe AuthorizedKeysCommand &quot;/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check&quot;: bad ownership or modes for directory /opt/gitlab/embedded/service/gitlab-shell/bin
Jan  6 06:50:15 UltGeek-GitLabServer sshd[116182]: error: Unsafe AuthorizedKeysCommand &quot;/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check&quot;: bad ownership or modes for directory /opt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the man page&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;AuthorizedKeysCommand
Specifies a program to be used to look up the user's public keys.  The program must be owned by root, not writable by group or others and specified by an absolute path.  Arguments to AuthorizedKeysCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used.
The program should produce on standard output zero or more lines of authorized_keys output (see AUTHORIZED_KEYS in sshd(8)). If a key supplied by AuthorizedKeysCommand does not successfully authenticate and authorize the user then public key authentication continues using the usual AuthorizedKeysFile files.  By default, no AuthorizedKeysCommand is run.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It turns out to be the wrong onwership or modes for the directory after I updated it. Then I update all the relative directory including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/opt&lt;/code&gt; because ssh panic when any of the directory is writable for other group or user with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod 0755 dir&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, it is back to working agagin. I do not sure if this makes any sense but it indeed get a better security.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Drop Inactive SSH Sessions</title>
   <link href="https://www.mai1015.com//linux/2019/01/03/drop-ssh-sessions/"/>
   <updated>2019-01-03T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//linux/2019/01/03/drop-ssh-sessions</id>
   <content type="html">&lt;p&gt;There will be many connect remain if we unexpectedly disconnected from the server. It remains inactive but still shows up when you type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;How to drop an ssh connection when unexpectedly disconnect from the server?&lt;/p&gt;

&lt;p&gt;we can command to solve the problem&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps -ef | grep sshd | grep -v root | grep -v 12345 | grep -v grep | awk '{print &quot;sudo kill -9&quot;, $2}' |sh &lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps -of&lt;/code&gt; displays all the process. Then we want to display only sshd session and drop your own ssh session. and then kill it with sh command.&lt;/p&gt;

&lt;p&gt;just to remember to replace 12345 with your pid. It won’t kill any root user session.&lt;/p&gt;

&lt;p&gt;If you are in linux you can try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pkill -o -u YOURUSERNAME sshd&lt;/code&gt; to kill oldest SSH session.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://unix.stackexchange.com/questions/127571/terminate-dropped-ssh-sessions&quot;&gt;Resource&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Convolutional Neural Network</title>
   <link href="https://www.mai1015.com//note/2018/12/29/convolutional-neural-networks/"/>
   <updated>2018-12-29T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2018/12/29/convolutional-neural-networks</id>
   <content type="html">&lt;h2 id=&quot;concept&quot;&gt;Concept&lt;/h2&gt;

&lt;p&gt;Basic neural network is pretty simple way to build and let computer learn from stuffs. It can actually become pretty smart after some time. However, it is hard to let it work with things like images.&lt;/p&gt;

&lt;p&gt;We have Convolutional Neural Network to make it easier.&lt;/p&gt;

&lt;h2 id=&quot;convolutional-neural-network&quot;&gt;Convolutional Neural Network&lt;/h2&gt;
&lt;p&gt;The basic concept are the same, but there are pre-processing for the image data.&lt;/p&gt;

&lt;h3 id=&quot;1-convolutional-operation&quot;&gt;1. Convolutional Operation&lt;/h3&gt;
&lt;p&gt;It takes the input image and apply Feature Detector via multiply each valuable value so respect to value to genertate Feature Map.&lt;/p&gt;

&lt;p&gt;We will create multiple feature map with different Feature Detector to obtain first convolutional layer.&lt;/p&gt;

&lt;h3 id=&quot;1b-relu-layer&quot;&gt;1b. ReLU Layer&lt;/h3&gt;
&lt;p&gt;Then we apply Rectifier Function to the Feature Map to break the linear because the image is not linear.
Detail: &lt;a href=&quot;https://arxiv.org/pdf/1502.01852.pdf&quot;&gt;Delving Deep into Rectifiers&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-max-pooling&quot;&gt;2. Max Pooling&lt;/h3&gt;
&lt;p&gt;We then reduce the size of the Feature by doing a Max Pooling to generate a small Pooled Feature Map. It reducing the number of parameters going in to the network. Also, it is harder to get overfitting.&lt;/p&gt;

&lt;h3 id=&quot;3-flattening&quot;&gt;3. Flattening&lt;/h3&gt;
&lt;p&gt;It basically take the numbers row by row and put it in to long column. Then it can fit in to neural network for processing.&lt;/p&gt;

&lt;h3 id=&quot;4-full-connection&quot;&gt;4. Full Connection&lt;/h3&gt;
&lt;p&gt;Rether than regular neural network, we have a fully connection network. It means the node is connected to all other nodes perivous layer.&lt;/p&gt;

&lt;h2 id=&quot;softmax--cross-entropy&quot;&gt;Softmax &amp;amp; Cross-Entropy&lt;/h2&gt;
&lt;h3 id=&quot;softmax&quot;&gt;Softmax&lt;/h3&gt;
&lt;p&gt;The result does not actually add up to one. so we apply a soft max to calculate the prectage.&lt;/p&gt;

\[\begin{align*}
f_{i}(z)=\frac{e^{z_{j}}}{\sum_{k}e^{z_{k}}}
\end{align*}\]

&lt;h3 id=&quot;cross-entropy&quot;&gt;Cross-Entropy&lt;/h3&gt;
&lt;p&gt;Loss function.&lt;/p&gt;

\[\begin{align*}
L_{i}=-\log{\frac{e^{f_{yi}}}{\sum_{j}e^{f_{j}}}}
\end{align*}\]

&lt;p&gt;Repesentation, is easier to calculate.&lt;/p&gt;

\[\begin{align*}
H(p,q)=-\sum p(x) \log q(x)
\end{align*}\]

</content>
 </entry>
 
 <entry>
   <title>Reinforcement Learning</title>
   <link href="https://www.mai1015.com//note/2018/12/24/reinforcement-learning/"/>
   <updated>2018-12-24T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2018/12/24/reinforcement-learning</id>
   <content type="html">&lt;h2 id=&quot;concept&quot;&gt;Concept&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;s - state&lt;/li&gt;
  &lt;li&gt;a - action&lt;/li&gt;
  &lt;li&gt;R - reward&lt;/li&gt;
  &lt;li&gt;\(\gamma\) - Discount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let AI know what they can do, and just let them know the things they can do.&lt;/p&gt;

&lt;p&gt;such as a maze, tell AI agent to move around. Give a reward (Reinforcement Learning) to the agent.&lt;/p&gt;

&lt;p&gt;How does agent remember to go out the maze? It distinguishes the path by giving it a value. One example is increasing the value of the path. However, we cannot assign the same value to all the action we take. Then we will introduce the Bellman equation.&lt;/p&gt;
&lt;h2 id=&quot;bellman-equation&quot;&gt;Bellman Equation&lt;/h2&gt;
&lt;p&gt;\(\begin{align*}
V(s)=\underset{\scriptstyle\text{a}}{max}(R(s,a) + \gamma V(s'))
\end{align*}\)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;s = current state&lt;/li&gt;
  &lt;li&gt;\(s'\) = next state&lt;/li&gt;
  &lt;li&gt;R is reward while the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;calculate the max reward, take the optimal state. \(\gamma\) eliminate the same value in the path. Inspire the agent to go on the right path.&lt;/p&gt;

&lt;p&gt;It basically builds a map.&lt;/p&gt;

&lt;p&gt;Additional: &lt;a href=&quot;https://www.rand.org/pubs/papers/P550.html&quot;&gt;Original Paper&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;markov-decision-process&quot;&gt;Markov Decision Process&lt;/h2&gt;
&lt;p&gt;Markov Decision process is a mathematical framework that helps decide thing with some random and under control.&lt;/p&gt;

&lt;p&gt;Using Bellman Equation,
\(V(s')\) becomes the expected value of all possible action. Does not know which state we are going into.
\(\begin{align*}
V(s)=\underset{\scriptstyle\text{a}}{max}(R(s,a) + \gamma \sum_{s'} P(s, a, s')V(s'))
\end{align*}\)&lt;/p&gt;

&lt;p&gt;p is the probability that the next step we take.
It gives probability to a different movement to get close to the destination.&lt;/p&gt;

&lt;h3 id=&quot;markov-property&quot;&gt;Markov Property&lt;/h3&gt;
&lt;p&gt;A stochastic process has the Markov property if the conditional probability distribution of future states of the process (conditional on both past and present states) depends only upon the present state, not on the sequence of events that preceded it. A process with this property is called a Markov process. (From &lt;a href=&quot;https://en.wikipedia.org/wiki/Markov_property&quot;&gt;wikipedia&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Interesting paper: &lt;a href=&quot;https://www.google.com/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=1&amp;amp;cad=rja&amp;amp;uact=8&amp;amp;ved=2ahUKEwjm9smw07nfAhWen4MKHYLSDdoQFjAAegQIChAC&amp;amp;url=http%3A%2F%2Fwww.cs.uml.edu%2Fecg%2Fuploads%2FAIfall14%2FMDPApplications3.pdf&amp;amp;usg=AOvVaw0pckXvWJBNr9T-yoDqBIRa&quot;&gt;A survey of applications of Markov decision processes&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;living-penalty&quot;&gt;Living Penalty&lt;/h3&gt;
&lt;p&gt;When we have that calculation, we will have a better result. However, how do we encourage them to do it faster?&lt;/p&gt;

&lt;p&gt;We can use punishment. For each movement, there will be a penalty. That way, it will try to go faster with less action.&lt;/p&gt;

&lt;h2 id=&quot;q-learning-intuition&quot;&gt;Q-Learning Intuition&lt;/h2&gt;

&lt;h3 id=&quot;what-is-q&quot;&gt;What is Q&lt;/h3&gt;
&lt;p&gt;Replace Q instead of V.
\(\begin{align*}
V(s)&amp;amp;=\underset{\scriptstyle\text{a}}{max}(Q(s,a))\\
Q(s, a)&amp;amp;=R(s,a)+\gamma\sum_{s'} (P(s, a, s')V(s'))\\
Q(s, a)&amp;amp;=R(s,a)+\gamma\sum_{s'} (P(s, a, s')\underset{a'}{max}(Q(s', a')))
\end{align*}\)&lt;/p&gt;

&lt;p&gt;V takes the maximum value. Q leaning takes all the possible action.&lt;/p&gt;

&lt;p&gt;In short: \(Q(s, a)=R(s,a)+\gamma \:\underset{a'}{max}(Q(s', a')))\)&lt;/p&gt;

&lt;p&gt;Detail: &lt;a href=&quot;https://pdfs.semanticscholar.org/968b/ab782e52faf0f7957ca0f38b9e9078454afe.pdf&quot;&gt;Markov Decision Processes: Concepts and Algorithms&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;temporal-difference&quot;&gt;Temporal Difference&lt;/h3&gt;
&lt;p&gt;\(\begin{align*}
TD(a, s) = R(s,a)+\gamma\:\underset{a'}{max}(Q(s', a'))-Q(s,a)
\end{align*}\)&lt;/p&gt;

&lt;p&gt;different in time. \(Q(s, a)\) action previously, new \(Q(s',a')\) now.&lt;/p&gt;

&lt;p&gt;Want to change small amount
\(\begin{align*}
TD(a, s) = R(s,a)+\gamma\:\underset{a'}{max}(Q(s', a'))-Q_{t-1}(s,a)\\
Q_{t}(s,a)=Q_{t-1}(s,a)+\alpha TD_{t}(a,s)
\end{align*}\)&lt;/p&gt;

&lt;p&gt;\(\alpha\) is the learning rate.&lt;/p&gt;

&lt;p&gt;Get TD() as close as possible to 0. Come up the optimal action.
\(\begin{align*}
Q_{t}(s,a)=Q_{t-1}(s,a)+\alpha (R(s,a)+\gamma\:\underset{a'}{max}(Q(s', a'))-Q_{t-1}(s,a))
\end{align*}\)&lt;/p&gt;

&lt;p&gt;Additional Reading: &lt;a href=&quot;https://link.springer.com/article/10.1007/BF00115009&quot;&gt;Learning to predict by the methods of temporal differences&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;deep-q-learning-intuition&quot;&gt;Deep Q-Learning Intuition&lt;/h2&gt;
&lt;p&gt;Simple Q learning is no longer suited for the complicated environment. We can use deep learning to calculate Q. Therefore, it is not limited to one simple rule and formula.&lt;/p&gt;

&lt;p&gt;The neural network will predict the Q value.
How to adapt the TD in Q value. calculate error/loss using bp to update the weight.&lt;/p&gt;

&lt;p&gt;Resource: &lt;a href=&quot;https://medium.com/@awjuliani/simple-reinforcement-learning-with-tensorflow-part-4-deep-q-networks-and-beyond-8438a3e2b8df&quot;&gt;Simple Reinforcement Learning with Tensorflow Part 4: Deep Q-Networks and Beyond&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;experience-replay&quot;&gt;Experience Replay&lt;/h3&gt;
&lt;p&gt;In some environment, there is a different condition that will help AI to learn. Such as a self-driven car, it learns how to drive a car. Each movement is necessary to go through the network. However, it cannot learn will by one piece. Therefore, it will remember a sequence of action as a batch. When it has enough information, it started to learn by viewing the batch. It can enchant the learning process. It will reduce the number of time to practice.&lt;/p&gt;

&lt;h3 id=&quot;action-selection-policies&quot;&gt;Action Selection Policies&lt;/h3&gt;
&lt;p&gt;When the network output the percentage of an action. How does the machine choose which action to take? There are many action selection policies. One example is “softmax” decide the action we take.&lt;/p&gt;

&lt;p&gt;In exploration, it will take as probability how often the action will take. Just randomly selecting the action.&lt;/p&gt;

&lt;p&gt;Resource: &lt;a href=&quot;http://tokic.com/www/tokicm/publikationen/papers/AdaptiveEpsilonGreedyExploration.pdf&quot;&gt;Adaptive ε-greedy Exploration in Reinforcement Learning Based on Value Differences&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>how bit torrent works</title>
   <link href="https://www.mai1015.com//note/2018/12/18/bittorrent/"/>
   <updated>2018-12-18T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2018/12/18/bittorrent</id>
   <content type="html">&lt;p&gt;Bit torrent is currently pretty popular way to download, besides this, there is PT as well.&lt;/p&gt;

&lt;p&gt;the advantage using bit torrent:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It is using peer-to-peer networking to do the file serving.&lt;/li&gt;
  &lt;li&gt;It contains the file information that checks if the file is corrupted.&lt;/li&gt;
  &lt;li&gt;It encourages people to upload their file, then people can download faster and share the portion that other client doesn’t have.&lt;/li&gt;
  &lt;li&gt;Torrent is open-sourced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;there will be a tracking server that keeps tracks all the people who downloaded the file, and they can make the file download faster when peer work together.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>P2P concept study</title>
   <link href="https://www.mai1015.com//note/2018/12/17/p2p-study/"/>
   <updated>2018-12-17T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//note/2018/12/17/p2p-study</id>
   <content type="html">&lt;h3 id=&quot;concept&quot;&gt;Concept&lt;/h3&gt;
&lt;p&gt;P2P is called peer-to-peer networking. It is kind of distributed application architecture.&lt;/p&gt;

&lt;p&gt;Peers are equally privileged, equipotent participants in the application. Each peer is a node.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/image/2018-12-18/1024px-P2P-network.png&quot; alt=&quot;peer-to-peer (P2P) network&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One example is the BitTorrent, there is a server as a tracker. It keeps all peers in one routing table. Each node will assign upon joining the network and assign a GUID. Then all peer that he contact will update the information and share to other peers.&lt;/p&gt;

&lt;p&gt;Upon leaving the network, the node will contact other peers that he is going to leave. Peers are going to remove him from the routing table.&lt;/p&gt;

&lt;p&gt;detail resources from: &lt;a href=&quot;http://tutorials.jenkov.com/p2p/index.html&quot;&gt;Peer-to-Peer (P2P) Networks&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;choord-vs-kademlia&quot;&gt;Choord vs. Kademlia&lt;/h3&gt;
&lt;p&gt;In Kademlia, routing table goes both ways. Peers have to notify others before leaving.&lt;/p&gt;

&lt;p&gt;In Choord, they are not symmetric. They do not need to keep each other. when leaving, they have to send leave a message to the one keeps them in the routing table.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introduction</title>
   <link href="https://www.mai1015.com//2018/12/17/introduction/"/>
   <updated>2018-12-17T00:00:00+00:00</updated>
   <id>https://www.mai1015.com//2018/12/17/introduction</id>
   <content type="html">&lt;p&gt;Hello, this is my new personal space to post blog and experiences.&lt;/p&gt;

&lt;p&gt;I will update some note and tutorial from my learning.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/atom.xml&quot;&gt;RSS feed&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 

</feed>
