<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xml:lang="en-US">
	<title>Angel's Blog</title>
	<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php" />
	<modified>2026-04-14T09:15:30Z</modified>
	<author>
		<name>Angel</name>
	</author>
	<copyright>Copyright 2026, Angel</copyright>
	<generator url="http://www.sourceforge.net/projects/sphpblog" version="0.7.0">SPHPBLOG</generator>
	<entry>
		<title>JAVA: Initializing Spring Boot Application</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry250602-032204" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>angelcool@lolcahost:~/code-learning/Java/spring-boot$ date<br />Sun Jun  1 12:30:32 PM PDT 2025<br />angelcool@lolcahost:~/code-learning/Java/spring-boot$ pwd<br />/home/angelcool/code-learning/Java/spring-boot<br /><br /># INITIALIZE APPLICATION<br />angelcool@lolcahost:~/code-learning/Java/spring-boot$ spring init -a my-demo -l java --build maven -x my-demo<br />Using service at <a href="https://start.spring.io" >https://start.spring.io</a><br />Project extracted to &#039;/home/angelcool/code-learning/Java/spring-boot/my-demo&#039;<br />angelcool@lolcahost:~/code-learning/Java/spring-boot$<br /><br /># INSTALL MAVEN<br />angelcool@localhost:~/code-learning/Java/spring-boot/my-demo$ sudo dnf install maven<br />...<br />angelcool@localhost:~/code-learning/Java/spring-boot/my-demo$ mvn --version<br />Apache Maven 3.9.6 (Red Hat 3.9.6-7)<br />...<br /><br /># RUN APPLICATION, NOTE: I think I had to update the artifactId in pom.xml to &#039;spring-boot-starter-web&#039;<br />angelcool@localhost:~/code-learning/Java/spring-boot/my-demo$ mvn spring-boot:run<br />...<br /><br /># MAKE REQUEST<br />angelcool@localhost:~/code-learning/Java/spring-boot/my-demo$ http  <a href="http://localhost:8080/coffees" >http://localhost:8080/coffees</a><br />HTTP/1.1 200 <br />Connection: keep-alive<br />Content-Type: application/json<br />Date: Mon, 02 Jun 2025 03:13:46 GMT<br />Keep-Alive: timeout=60<br />Transfer-Encoding: chunked<br /><br />[<br />    {<br />        &quot;id&quot;: &quot;3d1256a7-c5c8-4a9b-9ef3-60da3107b06b&quot;,<br />        &quot;name&quot;: &quot;Black&quot;<br />    },<br />    {<br />        &quot;id&quot;: &quot;7fc475b2-7c39-4412-baeb-6ac01f46128c&quot;,<br />        &quot;name&quot;: &quot;French Vanilla&quot;<br />    },<br />    {<br />        &quot;id&quot;: &quot;690c16af-3931-4dbd-b573-a9d8c86e0a3c&quot;,<br />        &quot;name&quot;: &quot;Hazelnut&quot;<br />    }<br />]<br /><br /># SOURCE CODE<br />angelcool@localhost:~/code-learning/Java/spring-boot/my-demo$ cat src/main/java/com/example/my_demo/DemoApplication.java <br />package com.example.my_demo;<br /><br />import org.springframework.boot.SpringApplication;<br />import org.springframework.boot.autoconfigure.SpringBootApplication;<br />// import org.springframework.stereotype.Controller;<br />import org.springframework.web.bind.annotation.RequestMapping;<br />// import org.springframework.web.bind.annotation.ResponseBody;<br />import org.springframework.web.bind.annotation.RestController;<br />// import org.springframework.ui.Model;<br />import java.util.ArrayList;<br />import java.util.List;<br />import org.springframework.web.bind.annotation.RequestMethod;<br />import java.util.UUID;<br /><br />@SpringBootApplication<br />public class DemoApplication {<br /><br />	public static void main(String[] args) {<br />		SpringApplication.run(DemoApplication.class, args);<br />	}<br />}<br /><br />class Coffee {<br />	private final String id;<br />	private String name;<br /><br />	public Coffee(String id, String name) {<br />		this.id = id;<br />		this.name = name;<br />	}<br /><br />	public Coffee (String name) {<br />		this(UUID.randomUUID().toString(),name);<br />	}<br /><br />	public String getId(){<br />		return this.id;<br />	}<br /><br />	public String getName(){<br />		return this.name;<br />	}<br /><br />	public void setName(String name){<br />		this.name = name;<br />	}<br />}<br /><br />@RestController<br />class RestApiController{<br />	private List&lt;Coffee&gt; coffees = new ArrayList&lt;&gt;();<br /><br />	public RestApiController(){<br />		this.coffees.addAll(List.of(<br />			new Coffee(&quot;Black&quot;),<br />			new Coffee(&quot;French Vanilla&quot;),<br />			new Coffee(&quot;Hazelnut&quot;)<br />		));<br />	}<br /><br />	@RequestMapping(value = &quot;/coffees&quot;, method = RequestMethod.GET)<br />	Iterable&lt;Coffee&gt; getCoffees() {<br />		return this.coffees;<br />	}<br />}<br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry250602-032204</id>
		<issued>2025-06-02T00:00:00Z</issued>
		<modified>2025-06-02T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Java: Installing Spring Boot CLI</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry250601-000603" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>angelcool@localhost:~$<br />angelcool@localhost:~$ date<br />Sat May 31 04:57:16 PM PDT 2025<br />angelcool@localhost:~$ cat /etc/redhat-release <br />Fedora release 41 (Forty One)<br />angelcool@localhost:~$ <br /># INSTALL SDKMAN<br />angelcool@localhost:~$ curl -s &quot;https://get.sdkman.io&quot; | bash<br />...<br /># CHECK SDKMAN VERSION<br />angelcool@localhost:~$ sdk version<br /><br />SDKMAN!<br />script: 5.19.0<br />native: 0.7.4 (linux x86_64)<br /><br /># INSTALL SPRING BOOT CLI<br />angelcool@localhost:~$ sdk install springboot<br />...<br /># CHECK SPRING BOOT CLI VERSION<br />angelcool@localhost:~$ spring --version<br />Spring CLI v3.5.0<br />angelcool@localhost:~$<br />angelcool@localhost:~$<br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry250601-000603</id>
		<issued>2025-06-01T00:00:00Z</issued>
		<modified>2025-06-01T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Using GNU comm to compare sorted files line by line. </title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry241218-034133" />
		<content type="text/html" mode="escaped"><![CDATA[This is similar to PHP&#039;s array_diff and Java&#039;s removeAll(). Helpful in finding diffs between lists of ids.<br /><br /><pre>angelcool@fedora-laptop$cat FILE1.txt <br />1<br />2<br />3<br />4<br />5<br />5<br />angelcool@fedora-laptop$cat FILE2.txt <br />1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />angelcool@fedora-laptop$comm -13 &lt;(sort FILE1.txt|uniq) &lt;(sort FILE2.txt|uniq)<br />6<br />7<br />8<br />9<br />angelcool@fedora-laptop$ man comm<br />...<br />       Compare sorted files FILE1 and FILE2 line by line.<br /><br />       When FILE1 or FILE2 (not both) is -, read standard input.<br /><br />       With  no  options,  produce three-column output.  Column one contains lines unique to FILE1, column two con‐<br />       tains lines unique to FILE2, and column three contains lines common to both files.<br /><br />       -1     suppress column 1 (lines unique to FILE1)<br /><br />       -2     suppress column 2 (lines unique to FILE2)<br /><br />       -3     suppress column 3 (lines that appear in both files)<br /><br />       --check-order<br />              check that the input is correctly sorted, even if all input lines are pairable<br /><br />       --nocheck-order<br />              do not check that the input is correctly sorted<br /><br />       --output-delimiter=STR<br />              separate columns with STR<br /><br />       --total<br />              output a summary<br /><br />       -z, --zero-terminated<br />              line delimiter is NUL, not newline<br /><br />       --help display this help and exit<br /><br />       --version<br />              output version information and exit<br /><br />       Note, comparisons honor the rules specified by &#039;LC_COLLATE&#039;.<br />...</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry241218-034133</id>
		<issued>2024-12-18T00:00:00Z</issued>
		<modified>2024-12-18T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Java: My First Servlet</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry241124-015310" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>angelcool@fedora-laptop$date<br />Sat Nov 23 05:57:16 PM PST 2024<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$java --version<br />openjdk 17.0.13 2024-10-15<br />OpenJDK Runtime Environment (Red_Hat-17.0.13.0.11-1) (build 17.0.13+11)<br />OpenJDK 64-Bit Server VM (Red_Hat-17.0.13.0.11-1) (build 17.0.13+11, mixed mode, sharing)<br />angelcool@fedora-laptop$jar --version<br />jar 17.0.13<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$pwd<br />/home/angelcool/java-practice/HelloWorldServlet<br />angelcool@fedora-laptop$tree<br />.<br />├── deploy<br />│   └── helloworld.war<br />├── Notes.txt<br />├── src<br />│   ├── HelloWorld.class<br />│   └── HelloWorld.java<br />└── web<br />    └── WEB-INF<br />        ├── classes<br />        │   └── com<br />        │       └── coolwriter<br />        │           └── helloworld<br />        │               └── HelloWorld.class<br />        └── web.xml<br /><br />9 directories, 6 files<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$cat Notes.txt <br /># Compile java class, this will create HelloWorld.class<br />angelcool@fedora-laptop$javac --class-path /usr/share/tomcat/lib/tomcat-servlet-api.jar src/HelloWorld.java<br /><br /># Copy compiled .class file to WEB-INF <br />angelcool@fedora-laptop$cp src/HelloWorld.class web/WEB-INF/classes/com/coolwriter/helloworld/<br /><br /># Create WAR file<br />angelcool@fedora-laptop$jar cvf deploy/helloworld.war -C web .<br /><br /># Move WAR file to Tomcat webapps directory<br />angelcool@fedora-laptop$sudo  cp deploy/helloworld.war /usr/share/tomcat/webapps/<br /><br /># Reload servlet in /manager page ( or restart Tomcat I think )<br /><br /># Access servlet: <a href="http://localhost:8080/helloworld/Hello" >http://localhost:8080/helloworld/Hello</a><br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$cat web/WEB-INF/web.xml <br />&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />&lt;web-app version=&quot;4.0&quot; xmlns=&quot;http://xmlns.jcp.org/xml/ns/javaee&quot;<br />   xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;<br />   xsi:schemaLocation=&quot;http://xmlns.jcp.org/xml/ns/javaee <br />   <a href="http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd&quot;&gt;" >http://xmlns.jcp.org/xml/ns/javaee/web- ... &quot;&gt;</a><br /><br />  &lt;display-name&gt;Hello World!&lt;/display-name&gt;<br /><br />  &lt;servlet&gt;<br />    &lt;servlet-name&gt;helloworld&lt;/servlet-name&gt;<br />    &lt;servlet-class&gt;com.coolwriter.helloworld.HelloWorld&lt;/servlet-class&gt;<br />  &lt;/servlet&gt;<br /><br />  &lt;servlet-mapping&gt;<br />    &lt;servlet-name&gt;helloworld&lt;/servlet-name&gt;<br />    &lt;url-pattern&gt;/Hello&lt;/url-pattern&gt;<br />  &lt;/servlet-mapping&gt;<br /><br />&lt;/web-app&gt;<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$cat src/HelloWorld.java <br />package com.coolwriter.helloworld;<br /><br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br />import java.util.*;<br /><br />public class HelloWorld extends HttpServlet<br />{<br />    public void doGet(HttpServletRequest request, HttpServletResponse response)<br />        throws IOException, ServletException<br />    {<br />        response.setContentType(&quot;text/html&quot;);<br /><br />        PrintWriter out = response.getWriter();<br />        <br />        String msg = this.getGreeting();<br /><br />        out.println(msg);<br />    }<br /><br />    private String getGreeting()<br />    {<br />        String msg = null;<br /><br />        int rand = (int) (Math.random() * (6)) +1;<br /><br />        switch (rand) {<br />        case 1:<br />            msg = &quot;Hello There!&quot;;<br />            break;<br />        case 2:<br />            msg = &quot;Hello Friend!&quot;;<br />            break;<br />        case 3:<br />            msg = &quot;Hello Stranger!&quot;;<br />            break;<br />        case 4:<br />            msg = &quot;Hello! My name is Angel!&quot;;<br />            break;<br />        default:<br />            msg = &quot;Hello World!&quot;;<br />        }<br /><br />        return msg;<br />    }<br />}<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry241124-015310</id>
		<issued>2024-11-24T00:00:00Z</issued>
		<modified>2024-11-24T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Java: Installing Tomcat in Fedora 39</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry241123-202018" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>angelcool@fedora-laptop$date<br />Sat Nov 23 12:00:14 PM PST 2024<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$cat /etc/redhat-release <br />Fedora release 39 (Thirty Nine)<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$dnf info tomcat<br />Last metadata expiration check: 0:42:59 ago on Sat 23 Nov 2024 11:18:54 AM PST.<br />Installed Packages<br />Name         : tomcat<br />Epoch        : 1<br />Version      : 9.0.96<br />Release      : 1.fc39<br />Architecture : noarch<br />Size         : 323 k<br />Source       : tomcat-9.0.96-1.fc39.src.rpm<br />Repository   : @System<br />From repo    : updates<br />Summary      : Apache Servlet/JSP Engine, RI for Servlet 4.0/JSP 2.3 API<br />URL          : <a href="http://tomcat.apache.org/" >http://tomcat.apache.org/</a><br />License      : ASL 2.0<br />Description  : Tomcat is the servlet container that is used in the official Reference<br />             : Implementation for the Java Servlet and JavaServer Pages technologies.<br />             : The Java Servlet and JavaServer Pages specifications are developed by<br />             : Sun under the Java Community Process.<br />             : <br />             : Tomcat is developed in an open and participatory environment and<br />             : released under the Apache Software License version 2.0. Tomcat is intended<br />             : to be a collaboration of the best-of-breed developers from around the world.<br /><br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$sudo dnf install tomcat<br />...<br />angelcool@fedora-laptop$sudo dnf install tomcat-admin-webapps<br />...<br />angelcool@fedora-laptop$sudo dnf install tomcat-docs-webapp<br />...<br />angelcool@fedora-laptop$sudo systemctl start tomcat.service<br />...</pre><br /><br />Enable admin user, uncomment the following in /etc/tomcat/tomcat-users.xml<br /><pre>&lt;role rolename=&quot;admin&quot;/&gt;<br />&lt;role rolename=&quot;admin-gui&quot;/&gt;<br />&lt;role rolename=&quot;admin-script&quot;/&gt;<br />&lt;role rolename=&quot;manager&quot;/&gt;<br />&lt;role rolename=&quot;manager-gui&quot;/&gt;<br />&lt;role rolename=&quot;manager-script&quot;/&gt;<br />&lt;role rolename=&quot;manager-jmx&quot;/&gt;<br />&lt;role rolename=&quot;manager-status&quot;/&gt;<br />&lt;user name=&quot;admin&quot; password=&quot;admin&quot; roles=&quot;admin,manager,admin-gui,admin-script,manager-gui,manager-script,manager-jmx,manager-status&quot; /&gt;</pre><br /><br />Restart server and go to: <a href="http://localhost:8080/manager/html" >http://localhost:8080/manager/html</a><br /><br />For reference:<br /><pre>angelcool@fedora-laptop$<br />angelcool@fedora-laptop$tree /usr/share/tomcat/webapps/<br />/usr/share/tomcat/webapps/<br />├── host-manager<br />│   ├── css<br />│   │   └── manager.css<br />│   ├── images<br />│   │   ├── asf-logo.svg<br />│   │   └── tomcat.svg<br />│   ├── index.jsp<br />│   ├── META-INF<br />│   │   └── context.xml<br />│   └── WEB-INF<br />│       ├── jsp<br />│       │   ├── 401.jsp<br />│       │   ├── 403.jsp<br />│       │   └── 404.jsp<br />│       ├── manager.xml<br />│       └── web.xml<br />└── manager<br />    ├── css<br />    │   └── manager.css<br />    ├── images<br />    │   ├── asf-logo.svg<br />    │   └── tomcat.svg<br />    ├── index.jsp<br />    ├── META-INF<br />    │   └── context.xml<br />    ├── status.xsd<br />    ├── WEB-INF<br />    │   ├── jsp<br />    │   │   ├── 401.jsp<br />    │   │   ├── 403.jsp<br />    │   │   ├── 404.jsp<br />    │   │   ├── connectorCerts.jsp<br />    │   │   ├── connectorCiphers.jsp<br />    │   │   ├── connectorTrustedCerts.jsp<br />    │   │   ├── sessionDetail.jsp<br />    │   │   └── sessionsList.jsp<br />    │   └── web.xml<br />    └── xform.xsl<br /><br />13 directories, 26 files<br />angelcool@fedora-laptop$</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry241123-202018</id>
		<issued>2024-11-23T00:00:00Z</issued>
		<modified>2024-11-23T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Miscellaneous Notes</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240706-235032" />
		<content type="text/html" mode="escaped"><![CDATA[Miscellaneous notes for troubleshooting, gathering information about a redis/valkey setup, etc.<br /><br /><pre>acool@acool-HP-EliteBook-8440p:~/redis-cluster$ date<br />Sat 06 Jul 2024 04:44:24 PM PDT<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli --version<br />redis-cli 5.0.7<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### Find out node&#039;s role<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7000 INFO|grep role<br />role:master<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### If node is master...<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7000 INFO|grep slave0<br />slave0:ip=127.0.0.1,port=7005,state=online,offset=7532,lag=0<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### Verify this node is slave...<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7005 INFO|grep role<br />role:slave<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### Find out node&#039;s master...<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7005 INFO | egrep &quot;master_(host|port)&quot;<br />master_host:127.0.0.1<br />master_port:7000<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### Find out node&#039;s mode...<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7003 INFO | egrep mode<br />redis_mode:cluster<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$  ###  List all cluster nodes<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7004 CLUSTER NODES<br />99f95692421cd04661c93ef9f09e058a7a80a6e4 127.0.0.1:7002@17002 master - 0 1720310325000 3 connected 10923-16383<br />8589237392750f2df8618bcda4e92e3996dda07a 127.0.0.1:7005@17005 slave 02c090059770ba140c14a1f26a16b3457fd58bf1 0 1720310324000 6 connected<br />c53fa6a32d9646c21549346716f01a5147cb8bb9 127.0.0.1:7001@17001 master - 0 1720310325468 2 connected 5461-10922<br />02c090059770ba140c14a1f26a16b3457fd58bf1 127.0.0.1:7000@17000 master - 0 1720310325000 1 connected 0-5460<br />ed206ea99f372d34dee37433b7747b5f2b2a3a40 127.0.0.1:7003@17003 slave c53fa6a32d9646c21549346716f01a5147cb8bb9 0 1720310325567 4 connected<br />05fe8b609e4b13d0510ed9b32b27b84502898595 127.0.0.1:7004@17004 myself,slave 99f95692421cd04661c93ef9f09e058a7a80a6e4 0 1720310323000 5 connected<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### This command seems to run INFO in all cluster nodes...                <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli --cluster call 127.0.0.1:7000 INFO|grep role<br />role:master<br />role:master<br />role:slave<br />role:slave<br />role:slave<br />role:master<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ### monitor node<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7005 monitor<br />...<br /></pre><br />Find out data directory and config path:<br /><pre>acool@acool-HP-EliteBook-8440p:~/redis-cluster$ ####### FIND PATH for rdb AND aof FILES!!!! #######<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli -c -p 7000 CONFIG GET dir<br />1) &quot;dir&quot;<br />2) &quot;/home/acool/redis-cluster/7000&quot;<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli --cluster call 127.0.0.1:7000 CONFIG GET dir<br />&gt;&gt;&gt; Calling CONFIG GET dir<br />127.0.0.1:7000: dir<br />/home/acool/redis-cluster/7000<br />127.0.0.1:7001: dir<br />/home/acool/redis-cluster/7001<br />127.0.0.1:7004: dir<br />/home/acool/redis-cluster/7004<br />127.0.0.1:7005: dir<br />/home/acool/redis-cluster/7005<br />127.0.0.1:7003: dir<br />/home/acool/redis-cluster/7003<br />127.0.0.1:7002: dir<br />/home/acool/redis-cluster/7002<br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ <br />acool@acool-HP-EliteBook-8440p:~/redis-cluster$ redis-cli --cluster call 127.0.0.1:7000 INFO | grep -i config_file<br />...<br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240706-235032</id>
		<issued>2024-07-06T00:00:00Z</issued>
		<modified>2024-07-06T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Valkey Cluster Demo</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240705-213550" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>[acool@localhost ~]$ date<br />Fri Jul  5 01:48:53 PM PDT 2024<br />[acool@localhost ~]$ cat /etc/redhat-release <br />Fedora release 38 (Thirty Eight)<br />[acool@localhost ~]$ sudo dnf install valkey<br />...<br />[acool@localhost ~]$ valkey-cli --version<br />valkey-cli 7.2.4<br />[acool@localhost ~]$<br />[acool@localhost ~]$ # just in case...<br />[acool@localhost ~]$ systemctl stop valkey.service<br />[acool@localhost ~]$ systemctl status valkey.service<br />...<br />[acool@localhost ~]$ which valkey-server<br />/usr/bin/valkey-server<br />[acool@localhost ~]$<br />[acool@localhost ~]$ mkdir valkey-cluster-demo<br />[acool@localhost ~]$ cd valkey-cluster-demo/<br />[acool@localhost valkey-cluster-demo]$ vim valkey.conf<br />...<br />[acool@localhost valkey-cluster-demo]$ cat valkey.conf<br />port 7000<br />cluster-enabled yes<br />cluster-config-file nodes.conf<br />cluster-node-timeout 5000<br />appendonly yes<br />[acool@localhost valkey-cluster-demo]$<br />[acool@localhost valkey-cluster-demo]$ mkdir cluster-test<br />[acool@localhost valkey-cluster-demo]$ cd cluster-test/<br />[acool@localhost cluster-test]$ mkdir -p {7000..7005}<br />[acool@localhost cluster-test]$ for i in {7000..7005}; do cp ../valkey.conf $i; done<br />[acool@localhost cluster-test]$ # open 7 tabs, update ports and start servers<br />[acool@localhost cluster-test]$ # TIP to update ports: for i in {0..5}; do  sed -i &#039;s/7000/700&#039;&quot;$i&quot;&#039;/g&#039;  &quot;700$i/redis.conf&quot; ; done<br />[acool@localhost cluster-test]$ cd 7000/<br />[acool@localhost 7000]$ /usr/bin/valkey-server ./valkey.conf<br />...<br />[acool@localhost valkey-cluster-demo] # create cluster<br />[acool@localhost valkey-cluster-demo]$ valkey-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1<br />...<br />[acool@localhost valkey-cluster-demo]$ valkey-cli -p 7000 cluster nodes<br />384d585df521f8588a03b57a38e871549c0e58c4 127.0.0.1:7001@17001 master - 0 1720214911355 2 connected 5461-10922<br />5d2edcbba8f394a612df5253bd19a9399f97f4ff 127.0.0.1:7002@17002 master - 0 1720214912358 3 connected 10923-16383<br />4cf4150f20ae444422f0dabbc29b0a75878b1a2d 127.0.0.1:7004@17004 slave c88d6bea070f64023a2c7f27831bbbd113b2ff03 0 1720214912000 1 connected<br />e40a58e318f277ce2d420f7cb77480d5643c28c4 127.0.0.1:7005@17005 slave 384d585df521f8588a03b57a38e871549c0e58c4 0 1720214913362 2 connected<br />c88d6bea070f64023a2c7f27831bbbd113b2ff03 127.0.0.1:7000@17000 myself,master - 0 1720214912000 1 connected 0-5460<br />5b13cd8e34b47890e88fb48e30a99174ba19b751 127.0.0.1:7003@17003 slave 5d2edcbba8f394a612df5253bd19a9399f97f4ff 0 1720214911354 3 connected<br />[acool@localhost valkey-cluster-demo]$<br />[acool@localhost valkey-cluster-demo]$<br />[acool@localhost valkey-cluster-demo]$ # To connect to Valkey Cluster, you&#039;ll need a cluster-aware Valkey client...<br />[acool@localhost valkey-cluster-demo]$ # ...store some keys<br />[acool@localhost valkey-cluster-demo]$ valkey-cli -c -p 7000<br />127.0.0.1:7000&gt; set firstname Angel<br />-&gt; Redirected to slot [7108] located at 127.0.0.1:7001<br />OK<br />127.0.0.1:7001&gt; set lastname Cool<br />OK<br />127.0.0.1:7001&gt;exit<br />[acool@localhost valkey-cluster-demo]$<br />[acool@localhost valkey-cluster-demo]$ # Retrive some keys<br />[acool@localhost valkey-cluster-demo]$ valkey-cli -c -p 7005<br />127.0.0.1:7005&gt; get lastname<br />-&gt; Redirected to slot [7726] located at 127.0.0.1:7001<br />&quot;Cool&quot;<br />127.0.0.1:7001&gt; get firstname<br />&quot;Angel&quot;<br />127.0.0.1:7001&gt;exit<br />[acool@localhost valkey-cluster-demo]$<br />[acool@localhost valkey-cluster-demo]$</pre><br /><br />TIP: Easy way to start all servers:<br /><pre>acool@acool-HP-EliteBook-8440p:~/redis-cluster$ for i in {0..5}; do  cd /home/acool/redis-cluster/700$i &amp;&amp; /usr/bin/redis-server redis.conf --daemonize yes; done</pre><br /><br />Bonus: Pub/Sub demo<br /><br /><pre>[acool@localhost valkey-cluster-demo]$ # TERMINAL 1<br />[acool@localhost valkey-cluster-demo]$ valkey-cli -c -p 7001<br />127.0.0.1:7001&gt; SUBSCRIBE channel-a<br />...<br />[acool@localhost valkey-cluster-demo]$ # TERMINAL 2<br />[acool@localhost valkey-cluster-demo]$ valkey-cli -c -p 7002<br />127.0.0.1:7002&gt; SUBSCRIBE channel-b<br />...<br /><br />[acool@localhost valkey-cluster-demo]$ # TERMINAL 3<br />[acool@localhost valkey-cluster-demo]$ valkey-cli -c -p 7000<br />127.0.0.1:7000&gt; PUBLISH channel-a &quot;Hello channel a!&quot;<br />(integer) 0<br />127.0.0.1:7000&gt; PUBLISH channel-b &quot;Hello channel b!&quot;<br />(integer) 0<br />127.0.0.1:7000&gt; <br />127.0.0.1:7000&gt; exit<br />[acool@localhost valkey-cluster-demo]$ # Monitor output in TERMINAL 1 and 2</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240705-213550</id>
		<issued>2024-07-05T00:00:00Z</issued>
		<modified>2024-07-05T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Elixir: Making Concurrent API Calls</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240413-024712" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>angelcool@fedora-laptop$<br />angelcool@fedora-laptop$date<br />Fri Apr 12 07:51:16 PM PDT 2024<br />angelcool@fedora-laptop$ls lib/<br />coolprogram.ex  coordinator.ex  worker.ex<br />angelcool@fedora-laptop$cat lib/coolprogram.ex <br />defmodule CoolProgram do<br />  def temperature_of(cities) do<br />    coordinator_pid = spawn(CoolProgram.Coordinator, :loop, [[], Enum.count(cities)])<br />    cities |&gt; Enum.each(fn city -&gt;<br />        worker_pid = spawn(CoolProgram.Worker, :loop, [])<br />        send(worker_pid, {coordinator_pid, city})<br />    end)<br />  end<br />end<br />angelcool@fedora-laptop$cat lib/coordinator.ex <br />defmodule CoolProgram.Coordinator do<br /><br />  def loop(results \\ [], results_expected) do<br />    receive do<br />      {:ok, result} -&gt;<br />        new_results = [result|results]<br />        if results_expected == Enum.count(new_results) do<br />          send(self(), :exit)<br />        end<br />        loop(new_results, results_expected)<br />      :exit -&gt;<br />          IO.puts(results |&gt; Enum.sort |&gt; Enum.join(&quot;, &quot;))<br />        _-&gt;<br />          loop(results, results_expected)<br />    end<br />  end<br /><br />end<br />angelcool@fedora-laptop$cat lib/worker.ex <br />defmodule CoolProgram.Worker do<br /><br />  def temperature_of(location) do<br />    result = url_for(location)<br />      |&gt; HTTPoison.get<br />      |&gt; parse_response<br />    case result do<br />      {:ok, temp} -&gt;<br />        &quot;#{location}: #{temp}° C&quot;<br />      :error -&gt;<br />        &quot;#{location} not found&quot;<br />    end<br />  end<br /><br />  defp url_for(location) do<br />    location = URI.encode(location)<br />    &quot;http://api.openweathermap.org/data/2.5/weather?q=#{location}&amp;appid=#{apikey()}&quot;<br />  end<br /><br />  defp parse_response({:ok, %HTTPoison.Response{body: body, status_code: 200}}) do<br />    body<br />      |&gt; JSON.decode!<br />      |&gt; compute_temperature()<br />  end<br /><br />  defp parse_response(_) do<br />    :error<br />  end<br /><br />  defp compute_temperature(json) do<br />    try do<br />      temp = (json[&quot;main&quot;][&quot;temp&quot;]-273.15)<br />        |&gt; Float.round(1)<br />      {:ok, temp}<br />    rescue<br />      _-&gt; :error<br />    end<br />  end<br /><br />  defp apikey do<br />    &quot;XXXXXXXXXXXXXXXXXXXXXXXXXXXX&quot;<br />  end<br /><br />  def loop do<br />    receive do<br />      {sender_pid, location}-&gt;<br />        send(sender_pid, {:ok, temperature_of(location)})<br />      _-&gt;<br />        IO.puts &quot;don&#039;t know how to process this message&quot;<br />    end<br />    loop()<br />  end<br />end<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$iex --version<br />IEx 1.15.7 (compiled with Erlang/OTP 26)<br />angelcool@fedora-laptop$iex -S mix<br />Compiling 1 file (.ex)<br />Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]<br /><br />Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)<br />iex(1)&gt; cities=[&quot;San Diego&quot;, &quot;Merida&quot;, &quot;Singapore&quot;, &quot;Los Angeles&quot;, &quot;Mexico City&quot;, &quot;Miami&quot;, &quot;Temecula&quot;, &quot;Buenos Aires&quot;, &quot;Ojai&quot; ]<br />[&quot;San Diego&quot;, &quot;Merida&quot;, &quot;Singapore&quot;, &quot;Los Angeles&quot;, &quot;Mexico City&quot;, &quot;Miami&quot;,<br /> &quot;Temecula&quot;, &quot;Buenos Aires&quot;, &quot;Ojai&quot;]<br />iex(2)&gt; CoolProgram.temperature_of(cities)<br />:ok<br />Buenos Aires: 17.0° C, Los Angeles: 14.7° C, Merida: 25.0° C, Mexico City: 22.8° C, Miami: 22.0° C, Ojai: 14.2° C, San Diego: 15.2° C, Singapore: 30.8° C, Temecula: 13.1° C<br />iex(3)&gt;<br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240413-024712</id>
		<issued>2024-04-13T00:00:00Z</issued>
		<modified>2024-04-13T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Elixir: Miscellaneous Notes</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240412-190002" />
		<content type="text/html" mode="escaped"><![CDATA[<pre># Filtering files in a directory by filename<br />angelcool@fedora-laptop$date<br />Fri Apr 12 12:02:42 PM PDT 2024<br />angelcool@fedora-laptop$iex<br />...<br />iex(90)&gt; &quot;/home/angelcool/Downloads&quot; \<br />...(90)&gt; |&gt; Path.join(&quot;**/*.rpm&quot;) \<br />...(90)&gt; |&gt; Path.wildcard \<br />...(90)&gt; |&gt; Enum.filter(fn fname -&gt; String.contains?(Path.basename(fname),&quot;dbeaver&quot;) end)<br />[&quot;/home/angelcool/Downloads/dbeaver-ce-24.0.2-stable.x86_64.rpm&quot;]</pre><br /><br /><pre># Making an HTTP GET request<br />iex(18)&gt; :inets.start()<br />:ok<br />iex(19)&gt; :ssl.start()<br />:ok<br />iex(20)&gt; :httpc.request(:get, {&#039;https://www.angelcool.net&#039;, []}, [ssl: :httpc.ssl_verify_host_options(true)], [])<br />...<br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240412-190002</id>
		<issued>2024-04-12T00:00:00Z</issued>
		<modified>2024-04-12T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Elixir: Clustering Elixir Nodes - Updating Shared State.</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240406-184727" />
		<content type="text/html" mode="escaped"><![CDATA[<pre><br />angelcool@fedora-laptop$ # Let&#039;s get the date and versions used<br />angelcool@fedora-laptop$date<br />Sat Apr  6 11:51:08 AM PDT 2024<br />angelcool@fedora-laptop$iex --version<br />IEx 1.15.7 (compiled with Erlang/OTP 26)<br />angelcool@fedora-laptop$mix --version<br />Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]<br /><br />Mix 1.15.7 (compiled with Erlang/OTP 26)<br />angelcool@fedora-laptop$mix phx.new --version<br />Phoenix installer v1.7.11<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$ # The gist of this post...<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$ # Terminal 1<br />angelcool@fedora-laptop$ iex --name a@127.0.0.1<br />iex(a@127.0.0.1)1&gt;<br /><br />angelcool@fedora-laptop$ #Terminal 2<br />angelcool@fedora-laptop$ iex --name b@127.0.0.1<br />Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]<br /><br />Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)<br />iex(b@127.0.0.1)1&gt; Node.connect :&quot;a@127.0.0.1&quot;<br />true<br />iex(b@127.0.0.1)2&gt; Node.list<br />[:&quot;a@127.0.0.1&quot;]<br />iex(b@127.0.0.1)3&gt;<br /><br /># Terminal 1<br />iex(a@127.0.0.1)&gt; Agent.start(<br />  fn -&gt; %{hello: &quot;world&quot;} end, <br />  name: {:global, GlobalAgent}<br />)<br />{:ok, #PID&lt;0.116.0&gt;} <br /><br /># Terminal 2<br />iex(b@127.0.0.1)4&gt; Agent.get {:global,GlobalAgent}, &amp;(&amp;1)<br />%{hello: &quot;world&quot;}<br /><br /># Terminal 2 - Update state<br />iex(b@127.0.0.1)5&gt; Agent.update {:global, GlobalAgent}, fn _ -&gt; %{hello: &quot;everyone!&quot;}  end<br />:ok<br />iex(b@127.0.0.1)6&gt;<br /><br /># Terminal 2 - Get new state<br />iex(b@127.0.0.1)6&gt; Agent.get {:global,GlobalAgent}, &amp;(&amp;1)<br />%{hello: &quot;everyone!&quot;}<br /><br /># Terminal 1 - Get new state<br />iex(a@127.0.0.1)2&gt; Agent.get {:global,GlobalAgent}, &amp;(&amp;1)<br />%{hello: &quot;everyone!&quot;}</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240406-184727</id>
		<issued>2024-04-06T00:00:00Z</issued>
		<modified>2024-04-06T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Elixir: Processes Talking Amongst Themselves</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240402-184103" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>angelcool@fedora-laptop$date<br />Tue Apr  2 11:31:57 AM PDT 2024<br />angelcool@fedora-laptop$mix new process-demo --app process_a<br />* creating README.md<br />* creating .formatter.exs<br />* creating .gitignore<br />* creating mix.exs<br />* creating lib<br />* creating lib/process_a.ex<br />* creating test<br />* creating test/test_helper.exs<br />* creating test/process_a_test.exs<br /><br />Your Mix project was created successfully.<br />You can use &quot;mix&quot; to compile it, test it, and more:<br /><br />    cd process-demo<br />    mix test<br /><br />Run &quot;mix help&quot; for more commands.<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$cd process-demo/<br />angelcool@fedora-laptop$ls -l<br />total 8<br />drwxr-xr-x. 1 angelcool angelcool  24 Apr  2 11:31 lib<br />-rw-r--r--. 1 angelcool angelcool 575 Apr  2 11:31 mix.exs<br />-rw-r--r--. 1 angelcool angelcool 476 Apr  2 11:31 README.md<br />drwxr-xr-x. 1 angelcool angelcool  66 Apr  2 11:31 test<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$cat lib/process_a.ex <br />defmodule ProcessA do<br />  def receiverA(count) do<br />    receive do<br />      {from, message} -&gt; send(from, {&quot;Greetings from ProcessA!.&quot;, message})<br />      receiverA(count+1)<br />    end<br />  end<br />end<br />angelcool@fedora-laptop$cat lib/process_b.ex <br />defmodule ProcessB do<br />  def initialize do<br />    pid_A = spawn(ProcessA, :receiverA, [1])<br />    recieverB(pid_A)<br />  end<br /><br />  def recieverB(pid_A) do<br />    receive do<br />      {message} -&gt;<br />        send(pid_A, {self(), message})<br />        recieverB(pid_A)<br />      {response, originalmessage} -&gt;<br />        IO.puts(&quot;Response: #{response}&quot;)<br />        IO.puts(&quot;Original Message: #{originalmessage}&quot;)<br />        recieverB(pid_A)<br />    end<br />  end<br />end<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$iex --version<br />IEx 1.15.7 (compiled with Erlang/OTP 26)<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$mix phx.new --version<br />Phoenix installer v1.7.11<br />angelcool@fedora-laptop$<br />angelcool@fedora-laptop$iex -S mix<br />Compiling 2 files (.ex)<br />Generated process_a app<br />Erlang/OTP 26 [erts-14.2.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]<br /><br />Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)<br />iex(1)&gt; pid_B = spawn(ProcessB, :initialize, [])<br />#PID&lt;0.166.0&gt;<br />iex(2)&gt; send(pid_B, {&quot;Hi! This is a message from process B!&quot;})<br />Response: Greetings from ProcessA!.<br />{&quot;Hi! This is a message from process B!&quot;}<br />Original Message: Hi! This is a message from process B!<br />iex(3)&gt; </pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240402-184103</id>
		<issued>2024-04-02T00:00:00Z</issued>
		<modified>2024-04-02T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Iperf - 1000BASE-LX SMF LC/LC Fiber Link Speed Test</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry240303-221911" />
		<content type="text/html" mode="escaped"><![CDATA[HOST A - SERVER<br /><pre><br />angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$ date<br />Sun Mar  3 02:04:35 PM PST 2024<br /><br />#IPv4<br />angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$ iperf -s<br />------------------------------------------------------------<br />Server listening on TCP port 5001<br />TCP window size:  128 KByte (default)<br />------------------------------------------------------------<br />[  1] local 192.168.1.184 port 5001 connected with 192.168.1.192 port 57642 (icwnd/mss/irtt=14/1448/515)<br />[ ID] Interval       Transfer     Bandwidth<br />[  1] 0.00-10.01 sec  1.10 GBytes   941 Mbits/sec<br />angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$<br />angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$<br /><br /># IPv6<br />angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$ iperf -s -V<br />------------------------------------------------------------<br />Server listening on TCP port 5001<br />TCP window size:  128 KByte (default)<br />------------------------------------------------------------<br />[  1] local 2603:8000:6a00:5748:xxxx:xxxx:xxxx:xxxx port 5001 connected with 2603:8000:6a00:5748:xxxx:xxxx:xxxx:xxxx port 56868 (icwnd/mss/irtt=13/1428/460)<br />[ ID] Interval       Transfer     Bandwidth<br />[  1] 0.00-10.02 sec  1.08 GBytes   928 Mbits/sec<br />angelcool@2603-8000-6a00-5748-xxxx-xxxx-xxxx-xxxx:~$<br /></pre><br /><br />HOST B - CLIENT<br /><pre><br />acool@localhost ~]$<br /># IPv4<br />[acool@localhost ~]$ iperf -c 192.168.1.184<br />------------------------------------------------------------<br />Client connecting to 192.168.1.184, TCP port 5001<br />TCP window size: 16.0 KByte (default)<br />------------------------------------------------------------<br />[  1] local 192.168.1.192 port 57642 connected with 192.168.1.184 port 5001 (icwnd/mss/irtt=14/1448/731)<br />[ ID] Interval       Transfer     Bandwidth<br />[  1] 0.00-10.02 sec  1.10 GBytes   940 Mbits/sec<br /><br /># IPv6<br />[acool@localhost ~]$ iperf -c 2603:8000:6a00:xxxx:xxxx:xxxx:xxxx<br />------------------------------------------------------------<br />Client connecting to 2603:8000:6a00:xxxx:xxxx:xxxx:xxxx, TCP port 5001<br />TCP window size: 16.0 KByte (default)<br />------------------------------------------------------------<br />[  1] local 2603:8000:6a00:5748:: port 56868 connected with 2603:8000:6a00:5748:xxxx:xxxx:xxxx:xxxx port 5001 (icwnd/mss/irtt=13/1428/783)<br />[ ID] Interval       Transfer     Bandwidth<br />[  1] 0.00-10.02 sec  1.08 GBytes   928 Mbits/sec<br />[acool@localhost ~]$ <br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry240303-221911</id>
		<issued>2024-03-03T00:00:00Z</issued>
		<modified>2024-03-03T00:00:00Z</modified>
	</entry>
	<entry>
		<title>SSL/TLS: Wildcard Certificate Generation</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry231116-031450" />
		<content type="text/html" mode="escaped"><![CDATA[Tested and working on 11/15/2023 ! <br /><br /><pre># Create root CA<br />[acool@localhost tls]$openssl req --x509 --nodes --days 3650 --newkey rsa:2048 --keyout ENT-CA.key --out ENT-CA.crt<br /><br /># Crate new key and signing request (Tip: remove --aes256 to remove passphrase requirement... I think)<br />Passphrase: mypassphrase<br />[acool@localhost tls]$openssl genrsa --out star-dev-localhost.key --aes256 2048<br />[acool@localhost tls]$openssl req --new --key star-dev-localhost.key --out star-dev-localhost.csr<br /><br /># Sign request<br />[acool@localhost tls]$openssl x509 --req --in star-dev-localhost.csr --CA ENT-CA.crt --CAkey ENT-CA.key --CAcreateserial --days 3650 --sha256 --extfile star-dev-localhost.cnf --out star-dev-localhost.crt<br /><br /># remove passphrase<br />[acool@localhost tls]$openssl rsa --in star-dev-localhost.key --out star-dev-localhost-nopassphrase.key<br /><br />[acool@localhost tls]$ cat star-dev-localhost.cnf <br />authorityKeyIdentifier = keyid,issuer<br />basicConstraints = CA:FALSE<br />keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment<br />subjectAltName = @alt_names<br /><br />[alt_names]<br />DNS.1 = *.dev.localhost<br />[acool@localhost tls]$<br />[acool@localhost tls]<br /><br /><br /># finally, import ENT-CA.crt certificate in Chrome<br /># chrome://settings/certificates</pre><br /><br />Configure Nginx:<br /><pre>...<br />listen 443 ssl;<br />ssl_certificate /etc/ssl/certs/star-dev-localhost.crt;<br />ssl_certificate_key /etc/ssl/certs/star-dev-localhost-nopassphrase.key;<br />...</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry231116-031450</id>
		<issued>2023-11-16T00:00:00Z</issued>
		<modified>2023-11-16T00:00:00Z</modified>
	</entry>
	<entry>
		<title>C 101: Foreach loop macro</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry230403-182101" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>[acool@localhost ~]$ <br />[acool@localhost ~]$ date<br />Mon Apr  3 11:17:50 AM PDT 2023<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ cat c-foreach-macro.c <br />#include &lt;stdio.h&gt;<br /><br />#define foreach(item, array) \<br />    for(int keep = 1, \<br />            count = 0,\<br />            size = sizeof (array) / sizeof *(array); \<br />        keep &amp;&amp; count != size; \<br />        keep = !keep, count++) \<br />      for(item = (array) + count; keep; keep = !keep)<br /><br />int main()<br />{<br />    int mynumbers[] = {5,20,35,62,8,74,89};<br />    <br />    char mygreeting[] = {&quot;Hello world!&quot;};<br /><br />    float myfloats[] = {1.6,6.9,5.8,43.5,1.1,0.9};<br /><br />    foreach(int *v, mynumbers) {<br />        printf(&quot;value: %d\n&quot;, *v);<br />    }<br /><br />    foreach(char *v, mygreeting) {<br />        printf(&quot;value: %c\n&quot;, *v);<br />    }<br /><br />    foreach(float *v, myfloats) {<br />        printf(&quot;value: %.2f\n&quot;, *v);<br />    }<br /><br />    return 0;<br />}<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ gcc c-foreach-macro.c -o c-foreach-macro<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ ./c-foreach-macro <br />value: 5<br />value: 20<br />value: 35<br />value: 62<br />value: 8<br />value: 74<br />value: 89<br />value: H<br />value: e<br />value: l<br />value: l<br />value: o<br />value:  <br />value: w<br />value: o<br />value: r<br />value: l<br />value: d<br />value: !<br />value: <br />value: 1.60<br />value: 6.90<br />value: 5.80<br />value: 43.50<br />value: 1.10<br />value: 0.90<br />[acool@localhost ~]$</pre><br /><br />Bonus - dumping output from preprocessor.<br /><pre>[acool@localhost ~]$ <br />[acool@localhost ~]$ gcc c-foreach-macro.c -E -o c-macro.preprocessed<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ cat c-macro.preprocessed<br />...<br />int main()<br />{<br />    int mynumbers[] = {5,20,35,62,8,74,89};<br /><br />    char mygreeting[] = {&quot;Hello world!&quot;};<br /><br />    float myfloats[] = {1.6,6.9,5.8,43.5,1.1,0.9};<br /><br />    for(int keep = 1, count = 0, size = sizeof (mynumbers) / sizeof *(mynumbers); keep &amp;&amp; count != size; keep = !keep, count++) for(int *v = (mynumbers) + count; keep; keep = !keep) {<br />        printf(&quot;value: %d\n&quot;, *v);<br />    }<br /><br />    for(int keep = 1, count = 0, size = sizeof (mygreeting) / sizeof *(mygreeting); keep &amp;&amp; count != size; keep = !keep, count++) for(char *v = (mygreeting) + count; keep; keep = !keep) {<br />        printf(&quot;value: %c\n&quot;, *v);<br />    }<br /><br />    for(int keep = 1, count = 0, size = sizeof (myfloats) / sizeof *(myfloats); keep &amp;&amp; count != size; keep = !keep, count++) for(float *v = (myfloats) + count; keep; keep = !keep) {<br />        printf(&quot;value: %.2f\n&quot;, *v);<br />    }<br /><br />    return 0;<br />}<br />[acool@localhost ~]$ <br /></pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry230403-182101</id>
		<issued>2023-04-03T00:00:00Z</issued>
		<modified>2023-04-03T00:00:00Z</modified>
	</entry>
	<entry>
		<title>C 101: Creating Child Processes With A Loop</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry221023-231122" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;sys/wait.h&gt;<br /><br />void child( int seconds );<br /><br />int children = 15;<br /><br />int main(void)<br />{<br />  printf(&quot;Parent ID %d, Main ID %d \n&quot;, getppid(), getpid()); <br /><br />  for(int i=0;i&lt;children;i++)<br />  {<br />    if(fork()==0)<br />    {<br />      child(children-i); // pass seconds to sleep<br />    }<br />    else<br />    {<br />      wait(NULL);<br />    }<br />  }<br />}<br /><br />void child(int seconds)<br />{<br />  printf(&quot;Parent ID %d, Child ID %d, Sleeping %d seconds.\n&quot;, getppid(), getpid(), seconds); <br />  sleep(seconds);<br />  exit(0);<br />}</pre><br /><pre>[acool@localhost C-Exercises]$ date<br />Sun Oct 23 04:14:24 PM PDT 2022<br />[acool@localhost C-Exercises]$<br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ gcc parent_children.c <br />[acool@localhost C-Exercises]$ ./a.out <br />Parent ID 4298, Main ID 10357 <br />Parent ID 10357, Child ID 10358, Sleeping 15 seconds.<br />Parent ID 10357, Child ID 10394, Sleeping 14 seconds.<br />Parent ID 10357, Child ID 10436, Sleeping 13 seconds.<br />Parent ID 10357, Child ID 10475, Sleeping 12 seconds.<br />Parent ID 10357, Child ID 10510, Sleeping 11 seconds.<br />Parent ID 10357, Child ID 10532, Sleeping 10 seconds.<br />Parent ID 10357, Child ID 10546, Sleeping 9 seconds.<br />Parent ID 10357, Child ID 10558, Sleeping 8 seconds.<br />Parent ID 10357, Child ID 10581, Sleeping 7 seconds.<br />Parent ID 10357, Child ID 10598, Sleeping 6 seconds.<br />Parent ID 10357, Child ID 10607, Sleeping 5 seconds.<br />Parent ID 10357, Child ID 10613, Sleeping 4 seconds.<br />Parent ID 10357, Child ID 10647, Sleeping 3 seconds.<br />Parent ID 10357, Child ID 10732, Sleeping 2 seconds.<br />Parent ID 10357, Child ID 10815, Sleeping 1 seconds.<br />[acool@localhost C-Exercises]$<br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ ps -A |grep a.out<br />  10357 pts/0    00:00:00 a.out<br />  10394 pts/0    00:00:00 a.out<br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ pstree -p 10357<br />a.out(10357)───a.out(10436)<br />[acool@localhost C-Exercises]$ <br /></pre><br />Slightly different version, in this version we don&#039;t wait() for each child individually.<br /><pre>#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;sys/wait.h&gt;<br /><br />void child( int seconds );<br /><br />int children = 15;<br /><br />int main(void)<br />{<br />  printf(&quot;Parent ID %d, Main ID %d \n&quot;, getppid(), getpid()); <br /><br />  for(int i=0;i&lt;children;i++)<br />  {<br />    if(fork()==0)<br />    {<br />      child(children-i); // pass seconds to sleep<br />    }<br />  }<br /><br />  while (wait(NULL) &gt; 0); // wait for all children to finish<br />}<br /><br />void child(int seconds)<br />{<br />  printf(&quot;Parent ID %d, Child ID %d, Sleeping %d seconds.\n&quot;, getppid(), getpid(), seconds); <br />  sleep(seconds);<br />  exit(0);<br />}</pre><br /><pre>[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ gcc parent_children.c <br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ ./a.out <br />Parent ID 4298, Main ID 14322 <br />Parent ID 14322, Child ID 14323, Sleeping 15 seconds.<br />Parent ID 14322, Child ID 14324, Sleeping 14 seconds.<br />Parent ID 14322, Child ID 14325, Sleeping 13 seconds.<br />Parent ID 14322, Child ID 14326, Sleeping 12 seconds.<br />Parent ID 14322, Child ID 14327, Sleeping 11 seconds.<br />Parent ID 14322, Child ID 14328, Sleeping 10 seconds.<br />Parent ID 14322, Child ID 14329, Sleeping 9 seconds.<br />Parent ID 14322, Child ID 14330, Sleeping 8 seconds.<br />Parent ID 14322, Child ID 14331, Sleeping 7 seconds.<br />Parent ID 14322, Child ID 14332, Sleeping 6 seconds.<br />Parent ID 14322, Child ID 14333, Sleeping 5 seconds.<br />Parent ID 14322, Child ID 14334, Sleeping 4 seconds.<br />Parent ID 14322, Child ID 14335, Sleeping 3 seconds.<br />Parent ID 14322, Child ID 14336, Sleeping 2 seconds.<br />Parent ID 14322, Child ID 14337, Sleeping 1 seconds.<br />[acool@localhost C-Exercises]$<br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ pstree -p 14322<br />a.out(14322)─┬─a.out(14323)<br />             ├─a.out(14324)<br />             ├─a.out(14325)<br />             ├─a.out(14326)<br />             ├─a.out(14327)<br />             ├─a.out(14328)<br />             ├─a.out(14329)<br />             ├─a.out(14330)<br />             ├─a.out(14331)<br />             ├─a.out(14332)<br />             ├─a.out(14333)<br />             ├─a.out(14334)<br />             └─a.out(14335)<br />[acool@localhost C-Exercises]$ ps -A |grep a.out<br />  14322 pts/0    00:00:00 a.out<br />  14323 pts/0    00:00:00 a.out<br />  14324 pts/0    00:00:00 a.out<br />  14325 pts/0    00:00:00 a.out<br />  14326 pts/0    00:00:00 a.out<br />  14327 pts/0    00:00:00 a.out<br />  14328 pts/0    00:00:00 a.out<br />  14329 pts/0    00:00:00 a.out<br />  14330 pts/0    00:00:00 a.out<br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ <br />[acool@localhost C-Exercises]$ pstree -p 14322<br />a.out(14322)─┬─a.out(14323)<br />             ├─a.out(14324)<br />             ├─a.out(14325)<br />             ├─a.out(14326)<br />             ├─a.out(14327)<br />             └─a.out(14328)<br />[acool@localhost C-Exercises]$<br />[acool@localhost C-Exercises]$</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry221023-231122</id>
		<issued>2022-10-23T00:00:00Z</issued>
		<modified>2022-10-23T00:00:00Z</modified>
	</entry>
	<entry>
		<title>C101: Printing Emojis</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry221022-190423" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>#include &lt;stdio.h&gt;<br />#include &lt;wchar.h&gt;<br />#include &lt;locale.h&gt;<br /><br />// multibyte array, each character is 4 bytes long<br />wchar_t mystring[] = L&quot;Angel Cool á 🤪 😁 ა&quot;;<br /><br />// [acool@localhost other]$ gcc -Wall -ggdb emoji-multibyte-array.c -o emoji-multibyte-array<br />int main()<br />{<br />    setlocale(LC_ALL,&quot;&quot;);<br /><br />    // print total number of characters in string<br />    wprintf(L&quot;wcslen of wchar_t mystring[]: %ld\n&quot;, wcslen(mystring));<br /><br />    // output string<br />    wprintf(L&quot;%ls\n&quot;,mystring);<br /><br />    // print one character<br />    wprintf(L&quot;Emoji : %lc\n&quot;, mystring[13]);<br /><br />    // print all <br />    for (int j = 0; j &lt; wcslen(mystring); ++j)<br />    {<br />        wprintf(L&quot;%lc,&quot;, mystring[j]);<br />    }<br /><br />    wprintf(L&quot;\n&quot;);<br /><br />    // size in bytes of string, it also includes 4 bytes for the null (\0) characters at the end it seems <br />    wprintf(L&quot;Size in bytes of mystring[]: %d\n&quot;, sizeof(mystring));<br /><br />    // print size of wchar_t data type<br />    wprintf(L&quot;wchar_t is %d bytes long!\n&quot;, sizeof(wchar_t));<br /><br />    return 0;<br />}</pre><br /><pre>[acool@localhost other]$ date<br />Sat Oct 22 12:05:24 PM PDT 2022<br />[acool@localhost other]$ gcc emoji-multibyte-array.c <br />[acool@localhost other]$ ./a.out <br />wcslen of wchar_t mystring[]: 18<br />Angel Cool á 🤪 😁 ა<br />Emoji : 🤪<br />A,n,g,e,l, ,C,o,o,l, ,á, ,🤪, ,😁, ,ა,<br />Size in bytes of mystring[]: 76<br />wchar_t is 4 bytes long!<br />[acool@localhost other]$</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry221022-190423</id>
		<issued>2022-10-22T00:00:00Z</issued>
		<modified>2022-10-22T00:00:00Z</modified>
	</entry>
	<entry>
		<title>C 101: Preventing Zombie Processes </title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry220923-200117" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/wait.h&gt;<br /><br />int main()<br />{<br />    pid_t pid;<br />    int status;<br /><br />    pid = fork();<br /><br />    if(pid&lt;0)<br />    {<br />        printf(&quot;Error: fork() returned %u.\n&quot;, pid);<br />        return 1;<br />    }<br /><br />    if(pid == 0)<br />    {<br />        printf(&quot;Child: PID is %u. Parent&#039;s PID is %u\n&quot;, getpid(), getppid());<br />        sleep(10);<br />        puts(&quot;Child: about to exit.\n&quot;);<br />        return 33;<br />    }<br />    else<br />    {<br />        printf(&quot;Parent: PID is %u. Child&#039;s PID is %u\n&quot;, getpid(), pid);<br /><br />        while((pid=waitpid(-1,&amp;status,WNOHANG)) == 0)<br />        {<br />            printf(&quot;Parent: No child has terminated.&quot;);<br />            printf(&quot;Parent: Going to sleep for 1 second.\n&quot;);<br />            sleep(1);<br />        }<br />    }<br /><br />    printf(&quot;Parent: child with PID %u &quot;, pid);<br /><br />    if(WIFEXITED(status)!=0)<br />    {<br />        printf(&quot;exited with status %u\n&quot;,WIFEXITED(status));<br />    }<br />    else<br />    {<br />        printf(&quot;exited abnormally\n&quot;);<br />    }<br /><br />    return 0;<br />}<br /></pre><br />Preventing Zombie Processes Using waitpid()<br />Listing 19.5 -Teach Yourself C For Linux Programming<br /><pre>[acool@localhost C-practice]$ gcc -Wall fork.c<br />[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ ./a.out <br />Parent: PID is 57544. Child&#039;s PID is 57545<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Child: PID is 57545. Parent&#039;s PID is 57544<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Parent: No child has terminated.Parent: Going to sleep for 1 second.<br />Child: about to exit.<br /><br />Parent: child with PID 57545 exited with status 1<br />[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry220923-200117</id>
		<issued>2022-09-23T00:00:00Z</issued>
		<modified>2022-09-23T00:00:00Z</modified>
	</entry>
	<entry>
		<title>C 101: Creating Structures</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry220823-035202" />
		<content type="text/html" mode="escaped"><![CDATA[Method 1:<br /><pre>// define it as a template<br />struct person {<br /> char first_name[50];<br /> char last_name[50];<br />};<br /><br />// create two instances of person<br />struct person Person1, Person2;<br /><br />// assign values to Person1<br />strcpy(Person1.first_name, &quot;Angel&quot;);<br />strcpy(Person1.last_name, &quot;Cool&quot;);<br /></pre><br />Method 2:<br /><pre>// define it and create two instances of it<br />struct car {<br /> char make[50];<br /> char color[50];<br />} Car1, Car2;<br /><br />// assign values to Car1<br />strcpy(Car1.make, &quot;Chevy&quot;);<br />strcpy(Car1.color, &quot;red&quot;);<br /></pre><br />Method 3:<br /><pre>// use &#039;typedef&#039; to create it<br />typedef struct {<br /> char first_name[50];<br /> char last_name[50];<br />} person;<br /><br />// create two instances of person (no &#039;struct&#039; keyword needed)<br />person Person1, Person2;<br /></pre><br />Method 1 example<br /><pre>[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ cat method_1.c <br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br /><br />void main(){<br />    struct person {<br />      char first_name[50];<br />      char last_name[50];<br />    };<br /><br />    // create two instances of person<br />    struct person Person1, Person2;<br /><br />    // assign values to Person1<br />    strcpy(Person1.first_name, &quot;Angel&quot;);<br />    strcpy(Person1.last_name, &quot;Cool&quot;);<br />    <br />    // print assigned values <br />    printf(&quot;Hello %s %s!\n&quot;, Person1.first_name, Person1.last_name);<br />}<br />[acool@localhost C-practice]$ gcc method_1.c -o method_1<br />[acool@localhost C-practice]$ ./method_1 <br />Hello Angel Cool!<br />[acool@localhost C-practice]$ <br /></pre><br />Method 2 example<br /><pre>[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ cat method_2.c <br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br /><br />void main(){<br />    // define it and create two instances of it<br />    struct car {<br />      char make[50];<br />      char color[50];<br />    } Car1, Car2;<br /><br />    // assign values to Car1<br />    strcpy(Car1.make, &quot;Chevy&quot;);<br />    strcpy(Car1.color, &quot;red&quot;);<br /><br />    // print assigned values<br />    printf(&quot;My %s %s.\n&quot;,Car1.color, Car1.make);<br />}<br />[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ gcc method_2.c -o method_2<br />[acool@localhost C-practice]$ ./method_2<br />My red Chevy.<br />[acool@localhost C-practice]$ </pre><br />Method 3 example<br /><pre>[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ cat method_3.c <br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br /><br />void main(){<br />    // use &#039;typedef&#039; to create it<br />    typedef struct {<br />      char first_name[50];<br />      char last_name[50];<br />    } person;<br /><br />    // create two instances of person (no &#039;struct&#039; keyword needed)<br />    person Person1, Person2;<br /><br />    // assign values to Person1<br />    strcpy(Person1.first_name, &quot;Andres Manuel&quot;);<br />    strcpy(Person1.last_name, &quot;Lopez-Obrador&quot;);<br /><br />    printf(&quot;Viva la 4T! Viva %s %s!\n&quot;, Person1.first_name, Person1.last_name);<br />}<br />[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ gcc method_3.c -o method_3<br />[acool@localhost C-practice]$ ./method_3<br />Viva la 4T! Viva Andres Manuel Lopez-Obrador!<br />[acool@localhost C-practice]$ <br />[acool@localhost C-practice]$ </pre><br /><br />Another example:<br /><pre>[acool@localhost ~]$ <br />[acool@localhost ~]$ <br />[acool@localhost ~]$ date<br />Wed Apr  5 02:18:30 PM PDT 2023<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ cat books.c <br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br />struct Books {<br />    char title[50];<br />    char author[50];<br />    char subject[100];<br />    int id;<br />};<br /><br />typedef struct {<br />    char title[50];<br />    char author[50];<br />    char subject[100];<br />    int id;<br />} eBooks;<br /><br />void printdetails(eBooks *myEbook, struct Books *myBook)<br />{<br />  printf( &quot;myBook id : %d\n&quot;, myBook-&gt;id);<br />  printf( &quot;myBook title : %s\n&quot;, myBook-&gt;title);<br />  printf( &quot;myBook author : %s\n&quot;, myBook-&gt;author);<br />  printf( &quot;myBook subject : %s\n&quot;, myBook-&gt;subject);<br />  <br />  printf(&quot;====================================\n&quot;);<br /><br />  printf( &quot;myEbook id : %d\n&quot;, myEbook-&gt;id);<br />  printf( &quot;myEbook title : %s\n&quot;, myEbook-&gt;title);<br />  printf( &quot;myEbook author : %s\n&quot;, myEbook-&gt;author);<br />  printf( &quot;myEbook subject : %s\n&quot;, myEbook-&gt;subject);<br />}<br /><br />int main()<br />{<br />    // Pay attention to this! ...two different ways to declare it.<br />   struct Books *myBook = (struct Books *) malloc(sizeof(struct Books));<br />   eBooks *myEbook = (eBooks *) malloc(sizeof(eBooks));<br /><br />   strcpy( myBook-&gt;title, &quot;C Programming&quot;);<br />   strcpy( myBook-&gt;author, &quot;Angel Cool&quot;); <br />   strcpy( myBook-&gt;subject, &quot;Programming C Structs Examples&quot;);<br />   myBook-&gt;id = 1;<br /> <br />   strcpy( myEbook-&gt;title, &quot;C Programming (eBook)&quot;);<br />   strcpy( myEbook-&gt;author, &quot;Angel Cool (eBook)&quot;); <br />   strcpy( myEbook-&gt;subject, &quot;Programming C Structs Examples (eBook)&quot;);<br />   myEbook-&gt;id = 2;<br /> <br />   printdetails(myEbook,myBook);<br /><br />   return 0;<br />}<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ <br />[acool@localhost ~]$ gcc books.c -o books<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ ./books <br />myBook id : 1<br />myBook title : C Programming<br />myBook author : Angel Cool<br />myBook subject : Programming C Structs Examples<br />====================================<br />myEbook id : 2<br />myEbook title : C Programming (eBook)<br />myEbook author : Angel Cool (eBook)<br />myEbook subject : Programming C Structs Examples (eBook)<br />[acool@localhost ~]$ <br />[acool@localhost ~]$ file books<br />books: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ea1090588d4c761da3060066a7d7a67b7db9caa6, for GNU/Linux 3.2.0, not stripped<br />[acool@localhost ~]$ <br />[acool@localhost ~]$</pre>]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry220823-035202</id>
		<issued>2022-08-23T00:00:00Z</issued>
		<modified>2022-08-23T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Terraform: AWS VPC with IPV6 support</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry210705-012044" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>[acool@localhost EC2-VPC]$ <br />[acool@localhost EC2-VPC]$ date<br />Sun Jul  4 06:19:34 PM PDT 2021<br />[acool@localhost EC2-VPC]$ cat /etc/redhat-release <br />Fedora release 33 (Thirty Three)<br />[acool@localhost EC2-VPC]$ aws --version<br />aws-cli/1.18.223 Python/3.9.5 Linux/5.12.13-200.fc33.x86_64 botocore/1.19.63<br />[acool@localhost EC2-VPC]$ terraform -v<br />Terraform v1.0.1<br />on linux_amd64<br />+ provider registry.terraform.io/hashicorp/aws v3.48.0<br />[acool@localhost EC2-VPC]$<br /></pre><br />The gist of this post:<br /><pre> <br />[acool@localhost EC2-VPC]$ <br />[acool@localhost EC2-VPC]$ cat main.tf <br /># extract public ssh key from private ssh key<br /># [acool@localhost EC2-VPC]$ ssh-keygen -y -f ./COOL_SSH_PRIVATEKEY.pem &gt; COOL_SSH_PUBLICKEY.pub <br /><br />// a.- set region to use<br />provider &quot;aws&quot; {<br />    region = &quot;us-east-2&quot;<br />}<br /><br />// b.- create ssh key pair<br />resource &quot;aws_key_pair&quot; &quot;COOL_KEY_PAIR&quot; {<br />  key_name   = &quot;COOL_SSH_KEYPAIR&quot;<br />  public_key = &quot;${file(&quot;./COOL_SSH_PUBLICKEY.pub&quot;)}&quot;<br />}<br /><br />// c.- create vpc resource<br />resource &quot;aws_vpc&quot; &quot;COOL_VPC&quot; {<br />    enable_dns_support = true<br />    enable_dns_hostnames = true<br />    assign_generated_ipv6_cidr_block = true<br />    cidr_block = &quot;10.0.0.0/16&quot;<br />}<br /><br />// d.- create subnet<br />resource &quot;aws_subnet&quot; &quot;COOL_VPC_SUBNET&quot; {<br />    vpc_id = &quot;${aws_vpc.COOL_VPC.id}&quot;<br />    cidr_block = &quot;${cidrsubnet(aws_vpc.COOL_VPC.cidr_block, 4, 1)}&quot;<br />    map_public_ip_on_launch = true<br /><br />    ipv6_cidr_block = &quot;${cidrsubnet(aws_vpc.COOL_VPC.ipv6_cidr_block, 8, 1)}&quot;<br />    assign_ipv6_address_on_creation = true<br />}<br /><br />// e.- create internet gateway<br />resource &quot;aws_internet_gateway&quot; &quot;COOL_GATEWAY&quot; {<br />    vpc_id = &quot;${aws_vpc.COOL_VPC.id}&quot;<br />}<br /><br />// f.- create routing table<br />resource &quot;aws_default_route_table&quot; &quot;COOL_VPC_ROUTING_TABLE&quot; {<br />    default_route_table_id = &quot;${aws_vpc.COOL_VPC.default_route_table_id}&quot;<br /><br />    route {<br />        cidr_block = &quot;0.0.0.0/0&quot;<br />        gateway_id = &quot;${aws_internet_gateway.COOL_GATEWAY.id}&quot;<br />    }<br /><br />    route {<br />        ipv6_cidr_block = &quot;::/0&quot;<br />        gateway_id = &quot;${aws_internet_gateway.COOL_GATEWAY.id}&quot;<br />    }<br />}<br /><br />// g.- create some sort of association needed<br />resource &quot;aws_route_table_association&quot; &quot;COOL_SUBNET_ROUTE_TABLE_ASSOCIATION&quot; {<br />    subnet_id      = &quot;${aws_subnet.COOL_VPC_SUBNET.id}&quot;<br />    route_table_id = &quot;${aws_default_route_table.COOL_VPC_ROUTING_TABLE.id}&quot;<br />}<br /><br />// h.- create security group<br />resource &quot;aws_security_group&quot; &quot;COOL_SECURITY_GROUP&quot; {<br />    name = &quot;COOL_SECURITY_GROUP&quot;<br />    vpc_id = &quot;${aws_vpc.COOL_VPC.id}&quot;<br />    <br />    ingress {<br />        from_port = 22<br />        to_port = 22<br />        protocol = &quot;tcp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    ingress {<br />        from_port = 22<br />        to_port = 22<br />        protocol = &quot;tcp&quot;<br />        ipv6_cidr_blocks = [&quot;::/0&quot;]<br />    }<br /><br />    // allow ping<br />    ingress{<br />        from_port = -1<br />        to_port = -1<br />        protocol = &quot;icmp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    // allow ping<br />    ingress{<br />        from_port = -1<br />        to_port = -1<br />        protocol = &quot;icmpv6&quot;<br />        ipv6_cidr_blocks = [&quot;::/0&quot;]<br />    }<br /><br />    egress {<br />      from_port = 0<br />      to_port = 0<br />      protocol = &quot;-1&quot;<br />      cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    egress {<br />      from_port = 0<br />      to_port = 0<br />      protocol = &quot;-1&quot;<br />      ipv6_cidr_blocks = [&quot;::/0&quot;]<br />    }<br />}<br /><br />// i.- create EC2 instance<br />resource &quot;aws_instance&quot; &quot;COOL_INSTANCE_APP01&quot; {<br />    ami = &quot;ami-01d5ac8f5f8804300&quot;<br />    key_name = &quot;COOL_SSH_KEYPAIR&quot;<br />    instance_type = &quot;t2.micro&quot;<br />    subnet_id = &quot;${aws_subnet.COOL_VPC_SUBNET.id}&quot;<br />    ipv6_address_count = 1<br />    vpc_security_group_ids = [&quot;${aws_security_group.COOL_SECURITY_GROUP.id}&quot;]<br /><br />    tags = {<br />        Name = &quot;COOL_INSTANCE_APP01&quot;<br />    }<br /><br />    depends_on = [aws_internet_gateway.COOL_GATEWAY]<br />}<br /><br />//j.- print instance IPs<br />output &quot;COOL_INSTANCE_APP01_IPv4&quot; {<br />  value = &quot;${aws_instance.COOL_INSTANCE_APP01.public_ip}&quot;<br />}<br /><br />output &quot;COOL_INSTANCE_APP01_IPv6&quot; {<br />  value = [&quot;${aws_instance.COOL_INSTANCE_APP01.ipv6_addresses}&quot;]<br />}<br />[acool@localhost EC2-VPC]$<br />[acool@localhost EC2-VPC]$ terraform init<br />...<br />[acool@localhost EC2-VPC]$ <br />[acool@localhost EC2-VPC]$ terraform apply<br />...<br />[acool@localhost EC2-VPC]$</pre><br /><br />Happy 4th of July, 2021! and cheers!<br /><br /><br />UPDATE - November 9, 2021<br />Added &#039;app_servers&#039; variable to create multiple aws_instances.<br />Commit message: &#039;Added EIP and specified private ip addresses.&#039;<br /><br />main.tf :<br /><pre><br /># extract public ssh key from private ssh key<br /># [acool@localhost EC2-VPC]$ ssh-keygen -y -f ./COOL_SSH_PRIVATEKEY.pem &gt; COOL_SSH_PUBLICKEY.pub <br /><br />// set region to use<br />provider &quot;aws&quot; {<br />    region = &quot;us-east-2&quot;<br />}<br /><br />// create ssh key pair<br />resource &quot;aws_key_pair&quot; &quot;COOL_KEY_PAIR&quot; {<br />  key_name   = &quot;COOL_SSH_KEYPAIR&quot;<br />  public_key = &quot;${file(&quot;./COOL_SSH_PUBLICKEY.pub&quot;)}&quot;<br />}<br /><br />// create vpc resource<br />resource &quot;aws_vpc&quot; &quot;COOL_VPC&quot; {<br />    enable_dns_support = true<br />    enable_dns_hostnames = true<br />    assign_generated_ipv6_cidr_block = true<br />    cidr_block = &quot;10.0.0.0/16&quot;<br />}<br /><br />// create subnet<br />resource &quot;aws_subnet&quot; &quot;COOL_PVC_SUBNET&quot; {<br />    vpc_id = &quot;${aws_vpc.COOL_VPC.id}&quot;<br />    cidr_block = &quot;${cidrsubnet(aws_vpc.COOL_VPC.cidr_block, 4, 1)}&quot;<br />    map_public_ip_on_launch = true<br /><br />    ipv6_cidr_block = &quot;${cidrsubnet(aws_vpc.COOL_VPC.ipv6_cidr_block, 8, 1)}&quot;<br />    assign_ipv6_address_on_creation = true<br />}<br /><br />// create internet gateway<br />resource &quot;aws_internet_gateway&quot; &quot;COOL_GATEWAY&quot; {<br />    vpc_id = &quot;${aws_vpc.COOL_VPC.id}&quot;<br />}<br /><br />// create routing table<br />resource &quot;aws_default_route_table&quot; &quot;COOL_VPC_ROUTING_TABLE&quot; {<br />    default_route_table_id = &quot;${aws_vpc.COOL_VPC.default_route_table_id}&quot;<br /><br />    route {<br />        cidr_block = &quot;0.0.0.0/0&quot;<br />        gateway_id = &quot;${aws_internet_gateway.COOL_GATEWAY.id}&quot;<br />    }<br /><br />    route {<br />        ipv6_cidr_block = &quot;::/0&quot;<br />        gateway_id = &quot;${aws_internet_gateway.COOL_GATEWAY.id}&quot;<br />    }<br />}<br /><br />// create some sort of association needed<br />resource &quot;aws_route_table_association&quot; &quot;COOL_SUBNET_ROUTE_TABLE_ASSOCIATION&quot; {<br />    subnet_id      = &quot;${aws_subnet.COOL_PVC_SUBNET.id}&quot;<br />    route_table_id = &quot;${aws_default_route_table.COOL_VPC_ROUTING_TABLE.id}&quot;<br />}<br /><br />// create security group<br />resource &quot;aws_security_group&quot; &quot;COOL_SECURITY_GROUP&quot; {<br />    name = &quot;COOL_SECURITY_GROUP&quot;<br />    vpc_id = &quot;${aws_vpc.COOL_VPC.id}&quot;<br />    <br />    ingress {<br />        from_port = 22<br />        to_port = 22<br />        protocol = &quot;tcp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    ingress {<br />        from_port = 22<br />        to_port = 22<br />        protocol = &quot;tcp&quot;<br />        ipv6_cidr_blocks = [&quot;::/0&quot;]<br />    }<br /><br />    // allow ping<br />    ingress{<br />        from_port = -1<br />        to_port = -1<br />        protocol = &quot;icmp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    // allow ping<br />    ingress{<br />        from_port = -1<br />        to_port = -1<br />        protocol = &quot;icmpv6&quot;<br />        ipv6_cidr_blocks = [&quot;::/0&quot;]<br />    }<br /><br />    egress {<br />      from_port = 0<br />      to_port = 0<br />      protocol = &quot;-1&quot;<br />      cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    egress {<br />      from_port = 0<br />      to_port = 0<br />      protocol = &quot;-1&quot;<br />      ipv6_cidr_blocks = [&quot;::/0&quot;]<br />    }<br />}<br /><br />// server names<br />variable app_servers {<br />    description = &quot;name of app servers&quot;<br />    type = list(map(any))<br />    default = [<br />        {name:&quot;COOL_LB01&quot;, ip:&quot;10.0.16.4&quot;},<br />        {name:&quot;COOL_LB02&quot;, ip:&quot;10.0.16.5&quot;},<br />        {name:&quot;COOL_APP01&quot;, ip:&quot;10.0.16.6&quot;},<br />        {name:&quot;COOL_APP02&quot;, ip:&quot;10.0.16.7&quot;},<br />    ]<br />}<br /><br />// create EC2 instance<br />resource &quot;aws_instance&quot; &quot;COOL_SERVERS&quot; {<br />    ami = &quot;ami-01d5ac8f5f8804300&quot;<br />    key_name = &quot;COOL_SSH_KEYPAIR&quot;<br />    instance_type = &quot;t2.micro&quot;<br />    subnet_id = &quot;${aws_subnet.COOL_PVC_SUBNET.id}&quot;<br />    ipv6_address_count = 1<br />    vpc_security_group_ids = [&quot;${aws_security_group.COOL_SECURITY_GROUP.id}&quot;]<br />    for_each = {for server in var.app_servers:  server.name =&gt; server}<br />    private_ip = each.value[&quot;ip&quot;]<br /><br />    tags = {<br />        Name = each.value[&quot;name&quot;]<br />    }<br /><br />    depends_on = [aws_internet_gateway.COOL_GATEWAY]<br />}<br /><br />// elastic IP<br />resource &quot;aws_eip&quot; &quot;COOL_EIP&quot; {<br />  instance = aws_instance.COOL_SERVERS[&quot;COOL_LB01&quot;].id<br />  vpc      = true<br />}<br /><br />// print instance IPs<br />output &quot;COOL_INSTANCE_APP01_IPv4&quot; {<br />    value = {for k, v in aws_instance.COOL_SERVERS: k =&gt; v.public_ip}<br />}<br /><br />output &quot;COOL_INSTANCE_APP01_IPv6&quot; {<br />  value = {for k, v in aws_instance.COOL_SERVERS: k =&gt; v.ipv6_addresses}<br />}<br /><br />output &quot;COOL_VPC_IPV6_BLOCK&quot; {<br />  value = aws_subnet.COOL_PVC_SUBNET.ipv6_cidr_block<br />}<br /><br />// SSH to instance:<br />// [acool@localhost EC2-VPC]$ ssh -i ./COOL_SSH_PRIVATEKEY.pem centos@ip_address<br /><br />// remove eip from COOL_LB01<br />// [acool@localhost EC2-VPC]$ aws ec2 disassociate-address --region us-east-2 --public-ip 3.131.249.150<br /><br />// assign eip to COOL_LB02, adjust instance id to match LB02. The same commands work to return eip to LB01<br />// [acool@localhost EC2-VPC]$ aws ec2 associate-address --region us-east-2 --public-ip 3.131.249.150 --instance-id i-05a634252654b7b34<br /></pre><br />]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry210705-012044</id>
		<issued>2021-07-05T00:00:00Z</issued>
		<modified>2021-07-05T00:00:00Z</modified>
	</entry>
	<entry>
		<title>Terraform: AWS EC2 single instance example.</title>
		<link rel="alternate" type="text/html" href="https://angelcool.net/sphpblog/blog_index.php?entry=entry210704-200235" />
		<content type="text/html" mode="escaped"><![CDATA[<pre>[acool@localhost terraform-tests]$ terraform --version<br />Terraform v1.0.1<br />...<br />[acool@localhost terraform-tests]$ aws --version<br />aws-cli/1.18.223 Python/3.9.5 Linux/5.12.12-200.fc33.x86_64 botocore/1.19.63<br />...<br /></pre><br />The gist of this post:<br /><pre>[acool@localhost EC2-SINGLE-INSTANCE]$ cat main.tf <br />provider &quot;aws&quot; {<br />    region = &quot;us-east-2&quot;<br />}<br /><br />// create ssh key<br />resource &quot;tls_private_key&quot; &quot;COOL_SSH_PK&quot; {<br />  algorithm = &quot;RSA&quot;<br />  rsa_bits  = 4096<br />}<br /><br />// create ssh key pair<br />resource &quot;aws_key_pair&quot; &quot;COOL_KEY_PAIR&quot; {<br />  key_name   = &quot;COOL_SSH_KEYNAME&quot;<br />  public_key = tls_private_key.COOL_SSH_PK.public_key_openssh<br /><br />  provisioner &quot;local-exec&quot; { # Create &quot;myKey.pem&quot; to your computer!!<br />    command = &quot;echo &#039;${tls_private_key.COOL_SSH_PK.private_key_pem}&#039; &gt; ./COOL_SSH_PK.pem&quot;<br />  }<br />}<br /><br />// create aws ec2 instance<br />resource &quot;aws_instance&quot; &quot;COOLAPP01&quot; {<br />    ami = &quot;ami-01d5ac8f5f8804300&quot;<br />    instance_type = &quot;t2.micro&quot;<br />    key_name = aws_key_pair.COOL_KEY_PAIR.key_name<br />    vpc_security_group_ids = [aws_security_group.COOLAPP01_security_group.id]<br /><br />  tags = {<br />    Name = &quot;COOLAPP01_tag_name&quot;<br />  }<br />}<br /><br />// create security group<br />resource &quot;aws_security_group&quot; &quot;COOLAPP01_security_group&quot; {<br /><br />    name=&quot;terraform_COOLAPP01_security_group&quot;<br /><br />    // allow port 80 tcp<br />    ingress{<br />        from_port = 80<br />        to_port = 80<br />        protocol = &quot;tcp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    // allow port 22 tcp<br />    ingress{<br />        from_port = 22<br />        to_port = 22<br />        protocol = &quot;tcp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    // allow ping<br />    ingress{<br />        from_port = -1<br />        to_port = -1<br />        protocol = &quot;icmp&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br /><br />    // allow all outbound traffic<br />    egress {<br />        from_port   = 0<br />        to_port     = 0<br />        protocol    = &quot;-1&quot;<br />        cidr_blocks = [&quot;0.0.0.0/0&quot;]<br />    }<br />}<br /><br />// TODO: enable IPV6<br /><br />output &quot;public_ip&quot; {<br />    value = aws_instance.COOLAPP01.public_ip<br />    description = &quot;public ip for COOLAPP01&quot;<br />}<br />[acool@localhost EC2-SINGLE-INSTANCE]$ <br />[acool@localhost EC2-SINGLE-INSTANCE]$terraform apply<br />...</pre><br /><br />Happy 4th of July, 2021 ya&#039;ll!!]]></content>
		<id>https://angelcool.net/sphpblog/blog_index.php?entry=entry210704-200235</id>
		<issued>2021-07-04T00:00:00Z</issued>
		<modified>2021-07-04T00:00:00Z</modified>
	</entry>
</feed>
