<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Attila Molnar</title>
    <description>The latest articles on DEV Community by Attila Molnar (@attilavm).</description>
    <link>https://dev.to/attilavm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53331%2F68d9d7ae-54da-442f-b9d2-be19619a4b56.png</url>
      <title>DEV Community: Attila Molnar</title>
      <link>https://dev.to/attilavm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/attilavm"/>
    <language>en</language>
    <item>
      <title>Search in your Jupyter notebooks from the CLI, fast.</title>
      <dc:creator>Attila Molnar</dc:creator>
      <pubDate>Mon, 15 May 2023 19:57:20 +0000</pubDate>
      <link>https://dev.to/attilavm/search-in-your-jupyter-notebooks-from-the-cli-fast-1408</link>
      <guid>https://dev.to/attilavm/search-in-your-jupyter-notebooks-from-the-cli-fast-1408</guid>
      <description>&lt;p&gt;My colleagues and I have written a large number of &lt;a href="https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb"&gt;Jupyter notebooks&lt;/a&gt;. It has been a common problem to search efficiently within them.&lt;/p&gt;

&lt;p&gt;Jupyter notebooks are JSON files, so using traditional search methods such as &lt;a href="https://www.gnu.org/software/grep/manual/grep.html"&gt;grep&lt;/a&gt; are tedious. Without a bit of tinkering it is 😉&lt;/p&gt;

&lt;p&gt;Initially, I found a script on the internet called "nbgrep", but it did not work out for us. So, I wrote my own version.&lt;/p&gt;

&lt;p&gt;It requires &lt;a href="https://stedolan.github.io/jq/"&gt;jq&lt;/a&gt; for JSON processing and GNU parallel for &lt;a href="https://www.gnu.org/software/parallel/"&gt;concurrent&lt;/a&gt; searches in the notebooks.&lt;/p&gt;

&lt;p&gt;These are awesome tools anyway and can be very handy for data scientists. &lt;code&gt;jq&lt;/code&gt; makes it easy to write queries against JSON files, while &lt;code&gt;parallel&lt;/code&gt; can be used to execute any kind of code concurrently, or even on multiple machines (using ssh) in a very simple way.&lt;/p&gt;

&lt;p&gt;They are easy to install:&lt;/p&gt;

&lt;p&gt;Debian and friends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;jq parallel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MacOS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;jq parallel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find my script as a gist &lt;a href="https://gist.github.com/AttilaVM/e2b71a4a4c0556c2fa6fb8c8183552aa#file-nbgrep"&gt;here&lt;/a&gt;,  or if you cannot install parallel for some reason, here is the &lt;a href="https://gist.github.com/AttilaVM/f653af3ec6d221d1dd8aeec645ea2cde"&gt;non-parallel version&lt;/a&gt;.  I wrote a non-parallel version specifically for this post, so please notify me if something is wrong.&lt;/p&gt;

&lt;p&gt;So when you run it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nbgrep &lt;span class="s1"&gt;'read_[a-z]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you will get something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./foo/bar.ipynb
        df_a = pd.read_csv(
        df_b = pd.read_csv(
./foobar/barfoo.ipynb
        G = obonet.read_obo(url)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(I had to rename most of the result)&lt;/p&gt;

&lt;p&gt;The script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

catch&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ERROR &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; occurred on &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'catch $? $LINENO'&lt;/span&gt; ERR

&lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;? You must provide a search pattern&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

jupyter-search&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nv"&gt;matches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; jq &lt;span class="s1"&gt;'.cells[].source[]'&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | xargs &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
  &lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; jupyter-search

find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-type&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-iname&lt;/span&gt; &lt;span class="s1"&gt;'*.ipynb'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-not&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt; &lt;span class="s1"&gt;'*/.ipynb_checkpoints/*'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
  | parallel jupyter-search &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's see how the script works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;#!/bin/bash&lt;/code&gt; just tells the kernel where to find the interpreter for the script.  &lt;code&gt;set -euo pipefail&lt;/code&gt; is bash's "strict mode". Without it, bash will not stop the script execution on an error &lt;code&gt;-e&lt;/code&gt; or on encountering undefined variables &lt;code&gt;-u&lt;/code&gt;. &lt;code&gt;-o pipefail&lt;/code&gt; will make sure that if any error happens (non-zero exit code) in a pipeline, then the whole pipeline will be considered erroneous.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;catch&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ERROR &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; occurred on &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'catch $? $LINENO'&lt;/span&gt; ERR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By trapping errors this way, we can see on which line the error occurred.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;? You must provide a search pattern&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the search pattern that you want to find in the notebooks. It can be any Perl-like regex pattern. This line will also provide a helpful error message if the search pattern is not provided.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jupyter-search&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nv"&gt;matches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; jq &lt;span class="s1"&gt;'.cells[].source[]'&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | xargs &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
  &lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$matches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a bash function definition. This function has two arguments: &lt;code&gt;$file&lt;/code&gt;, read from the first positional argument, and the search &lt;code&gt;$pattern&lt;/code&gt;, read from the second one. Let's concentrate on the search part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;matches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; jq &lt;span class="s1"&gt;'.cells[].source[]'&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | xargs &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;%"&lt;/span&gt;
  &lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the output of the pipeline (commands connected by pipes &lt;code&gt;|&lt;/code&gt;) will be assigned to the &lt;code&gt;matches&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;The first command of the pipeline reads the notebook into the &lt;code&gt;jq&lt;/code&gt; JSON processor, which extracts all code cells. These are piped into a grep command which applies the given &lt;code&gt;$pattern&lt;/code&gt; as a Perl-like regexp &lt;code&gt;-P&lt;/code&gt;. The last command in the pipeline will tabulate the matches found by &lt;code&gt;grep&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The if statement at the end of the function will print the results, given that &lt;code&gt;$matches&lt;/code&gt; is not an empty string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; jupyter-search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;parallel&lt;/code&gt; will execute the given code in a sub-shell, which will not inherit the variables from the parent shell (the shell executing the script itself). Therefore, it is necessary to export the previously defined function, so that it will be accessible in the sub-shell created by parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-type&lt;/span&gt; &lt;span class="s1"&gt;'f'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-iname&lt;/span&gt; &lt;span class="s1"&gt;'*.ipynb'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-not&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt; &lt;span class="s1"&gt;'*/.ipynb_checkpoints/*'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
  | parallel jupyter-search &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will find all regular files (excluding symlinks, directories and device files) with the &lt;code&gt;.ipynb&lt;/code&gt; extension in a case-insensitive manner. It will search recursively in the directory where you started the script, omitting only the &lt;code&gt;.ipynb_checkpoints&lt;/code&gt; directories. The found notebook files are streamed into the &lt;code&gt;parallel&lt;/code&gt; command which applies the &lt;code&gt;jupyter-search&lt;/code&gt; function on them with the given search &lt;code&gt;$pattern&lt;/code&gt; in as many parallel processes as your CPU core number. All of these processes will send their results onto your standard output, but parallel tidies them up so it will not be messy.&lt;/p&gt;

&lt;p&gt;So in conclusion we have a very fast way to search in Jupyter notebooks from the command line. I hope some of you will find it helpful. If you have ideas about how to improve it, I am open to suggestions.&lt;/p&gt;

</description>
      <category>jupyter</category>
      <category>datascience</category>
      <category>python</category>
      <category>cli</category>
    </item>
    <item>
      <title>Solution-diffusion model in Rust</title>
      <dc:creator>Attila Molnar</dc:creator>
      <pubDate>Sun, 14 May 2023 18:49:09 +0000</pubDate>
      <link>https://dev.to/attilavm/solution-diffusion-model-in-rust-2j8</link>
      <guid>https://dev.to/attilavm/solution-diffusion-model-in-rust-2j8</guid>
      <description>&lt;p&gt;I decided to go on an adventure. I will write a simple biological cell simulator in Rust. This is my first time to write a simulator and also my first time using Rust.&lt;/p&gt;

&lt;p&gt;In the early stage it will be useful only for the better understanding of already known biological concepts. However, later hopefully it will help to experiment with evolutionary and pharmacological questions. My long term goal is to simulate multiple &lt;a href="https://en.wikipedia.org/wiki/Escherichia_coli"&gt;Escherichia coli&lt;/a&gt; bacteria in a complex environment. These bacteria are very well studied, thanks to their significance in human and animal health. They can be both beneficial as &lt;a href="https://internationalprobiotics.org/e-coli-nissle-1917/"&gt;probiotics&lt;/a&gt; or harmful as &lt;a href="https://www.hopkinsmedicine.org/health/conditions-and-diseases/escherichia-coli-o157-h7"&gt;pathogens&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9-dwYH-2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vehabq8dhdoha7hpvvmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9-dwYH-2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vehabq8dhdoha7hpvvmw.png" alt="The cutest Escherichia coli ever drawn with a Rust logo in its center" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have choosen Rust, because it is a fast, low level language. It has &lt;a href="https://kornel.ski/rust-c-speed"&gt;comparable performance&lt;/a&gt; to C and C++, but unlike them it has a built-in and streamlined &lt;a href="https://doc.rust-lang.org/cargo/"&gt;solution&lt;/a&gt; for package management and documentation generation. I was able to use them in 5 minutes as a first timer.&lt;/p&gt;

&lt;p&gt;However the most telling indicator, that I was able to write the most simple proof of concept in around an hour. Somehow the language abstractions are similar to how I like to model problems in my head, which is deeply subjective, but still it strengthened my decision.&lt;/p&gt;

&lt;p&gt;I plan to work in baby steps, so first I programmed a very simple diffusion model.&lt;/p&gt;

&lt;p&gt;If you did not hear about diffusion, its basic explanation is easy. Given you have a water tank and you infuse it with oxygen or with some other soluble substance, then the particles of that substance can traverse freely in any direction.&lt;/p&gt;

&lt;p&gt;So given time, they will be more or less dispersed in the water tank uniformly. However, if you divide the water tank with a membrane, then you will have the same result, but after a longer time period. The time delay will be dependent on the membrane permeability for that given substance. The lower the permeability, the longer time you must wait.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2nIA3zHy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n5o2dbxuxlob3grz7cr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2nIA3zHy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9n5o2dbxuxlob3grz7cr.png" alt="my drawing showing molecule diffusion as red dots in a 2D water tank without a membrane and in another one with a membrane" width="720" height="1093"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wrote pseudo-code-like python script to provide the simplest model for this problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;membrane_permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;o2_forward&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;o2_reverse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;o2_forward&lt;/span&gt;
    &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;o2_reverse&lt;/span&gt;

    &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;o2_reverse&lt;/span&gt;
    &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;o2_forward&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt;


&lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;
&lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;o2_permeability&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cycle&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;membrane_permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cycle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a_solvent_o2_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b_solvent_o2_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Rust implementation logically is almost the same, but for 3 equal volume solvent spaces across 2 membranes between them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zxymbU5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pzvqcyj9m5iothxi67i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zxymbU5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pzvqcyj9m5iothxi67i.png" alt="my drawing an extremely oversimplified model of the solvent spaces of a gram negative bacteria, a big rectangle subdivided into three equal size smaller rectangles for exosol (extracellular environment, periplasm and cytosol)" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well it is almost a gram negative bacteria, only a few parts are missing. XD&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e3gZ7n2R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zj9bopx8vo4h5isciyqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e3gZ7n2R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zj9bopx8vo4h5isciyqy.png" alt="This image represents a gram negative bacteria it is still simplified, but shows that the aforementioned solvent spaces are not equal in size, and also there are much more objects present inside and outside the cell surface, such as cell wall and membrane proteins" width="800" height="401"&gt;&lt;/a&gt;&lt;br&gt;
(&lt;a href="https://en.wikipedia.org/wiki/Gram-negative_bacteria"&gt;image source wikipedia&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Also you should note that I came up with the term "exosol". So on your quiz you should write what your teacher said, which will be most likely "extracellular environment" which is long and boring but will be the right answer.&lt;/p&gt;

&lt;p&gt;Back to the topic: I fell in love with rust, because with the &lt;a href="https://doc.rust-lang.org/book/ch10-02-traits.html"&gt;trait&lt;/a&gt; language feature I was able to program diffusion in a very close way to how I would reason about it:&lt;/p&gt;

&lt;p&gt;"Diffusion is based on the trait of membranes that they can permeate molecules between solvents, which they separate"&lt;/p&gt;

&lt;p&gt;and one of the most important attributes of every code is how easy it is to reason about it.&lt;/p&gt;

&lt;p&gt;So let's see the code:&lt;/p&gt;

&lt;p&gt;First I defined the &lt;code&gt;Solvent&lt;/code&gt; struct, which has only one field, the oxygen molecule count. Rust structs seems very similar to C structs, but &lt;a href="https://levelup.gitconnected.com/from-c-to-rust-part-iii-44c9dce4f5d3"&gt;differ&lt;/a&gt; in some important ways. The most important difference is regarding this code is the ability in Rust to implement functions bound to a struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;o2_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I defined the &lt;code&gt;Membrane&lt;/code&gt; also as a struct, has a sole field, its permeability for molecular oxygen, expressed as a simple factor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Membrane&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I defined the &lt;code&gt;Permeate&lt;/code&gt; trait, which has a method with 2 solvents as it parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Permeate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I implemented the &lt;code&gt;Permeate&lt;/code&gt; trait for the &lt;code&gt;Membrane&lt;/code&gt; struct. I just calculated the amount of oxygen flux in both directions by multiplying the oxygen count in the given simulation cycle with the membrane permeability factor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Permeate&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Membrane&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;o2_forward&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.o2_permeability&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;o2_reverse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.o2_permeability&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o2_forward&lt;/span&gt;&lt;span class="nf"&gt;.round&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o2_reverse&lt;/span&gt;&lt;span class="nf"&gt;.round&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solvent1&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o2_reverse&lt;/span&gt;&lt;span class="nf"&gt;.round&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solvent2&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o2_forward&lt;/span&gt;&lt;span class="nf"&gt;.round&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly in the &lt;code&gt;main&lt;/code&gt; function I declare the players: &lt;code&gt;extrasol&lt;/code&gt;, &lt;code&gt;periplasm&lt;/code&gt;, &lt;code&gt;cytosol&lt;/code&gt;, &lt;code&gt;outer_membrane&lt;/code&gt; and &lt;code&gt;inner_membrane&lt;/code&gt;. So in a simulation loop I can calculate the diffusion across the two membranes.&lt;/p&gt;

&lt;p&gt;The most important two lines are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;outer_membrane&lt;/span&gt;&lt;span class="nf"&gt;.permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;extrasol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;periplasm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;inner_membrane&lt;/span&gt;&lt;span class="nf"&gt;.permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;periplasm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;cytosol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all it takes to calculate the diffusion in every simulation cycle. It is so tidy.&lt;/p&gt;

&lt;p&gt;However here is the full main function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;extrasol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;o2_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;periplasm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;o2_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;cytosol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Solvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;o2_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;outer_membrane&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Membrane&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;inner_membrane&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Membrane&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;o2_permeability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cycle,extrasol_o2,periplasm_o2,cytosol_o2"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cycle&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"{},{},{},{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extrasol&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;periplasm&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cytosol&lt;/span&gt;&lt;span class="py"&gt;.o2_count&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;outer_membrane&lt;/span&gt;&lt;span class="nf"&gt;.permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;extrasol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;periplasm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;inner_membrane&lt;/span&gt;&lt;span class="nf"&gt;.permeate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;periplasm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;cytosol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it was a nice experience. In the next version I will step up my game by developing a more sophisticated diffusion model, because now I am very far away from a strong model. One of the most obvious limitations is that in reality those solvents have vastly different volumes. Also the membrane surface areas should be considered. So I will further develop the model using  Fick's law. Which I will explain in the next post.&lt;/p&gt;

&lt;p&gt;But nevertheless I have a very simple model as a starting point on my way to a nicer bacteria model and I also learnt a bit of Rust, which was joyful.&lt;/p&gt;

&lt;p&gt;This project is free and open source under GPL 3.0 license,and can be found on &lt;a href="https://github.com/AttilaVM/simcoli"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>simulation</category>
      <category>biology</category>
      <category>bioinformatics</category>
    </item>
    <item>
      <title>Inspect your node application on a different machine</title>
      <dc:creator>Attila Molnar</dc:creator>
      <pubDate>Thu, 09 Aug 2018 15:41:39 +0000</pubDate>
      <link>https://dev.to/attilavm/inspect-your-node-application-on-a-different-machine-3laf</link>
      <guid>https://dev.to/attilavm/inspect-your-node-application-on-a-different-machine-3laf</guid>
      <description>&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;You wrote a node app, which works on your workstation but not on your server, and you plan to use your Chrome to debug the remote app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Warning
&lt;/h2&gt;

&lt;p&gt;Debugging anything on a public server, especially on a production server, is an extremely typical way to a monday morning mistake. If your server runs in a container or in a virtual machine, you can use Docker or Vagrant to run an equivalent instance on your local machine, and the method below will still work, it will be even faster without the extra networking overhead. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Thankfully our problem is fairly easy to solve with the all powerful &lt;a href="https://en.wikipedia.org/wiki/Secure_Shell" rel="noopener noreferrer"&gt;SSH&lt;/a&gt; command, which among other breathtaking features allows you to forward TCP connections from your local machine to your host or vica-versa. So we will forward connections directed to the node debugging port on our workstation to our host.  &lt;/p&gt;

&lt;p&gt;1) On the host start your app with the &lt;code&gt;--inspect&lt;/code&gt; switch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;node &lt;span class="nt"&gt;--inspect&lt;/span&gt; myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the output you should seek a line like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Debugger listening on ws://127.0.0.1:9229/e9580cde-b1ee-4ed1-a23b-e8178390b1b9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It tells us two important things. First the IP &lt;code&gt;127.0.0.1&lt;/code&gt; ensures us that the debugger won't accept any connection from the network, which may have some shady characters lurking around, especially if you are doing this on the Internet against my warning, then let me hold your beer in awe.&lt;/p&gt;

&lt;p&gt;Second the &lt;code&gt;9229&lt;/code&gt; number just after the IP is the port number used by the debugger, eager to accept a connection from our local chrome.&lt;/p&gt;

&lt;p&gt;2) Type the following command on the local machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; ssh &lt;span class="nt"&gt;-L9229&lt;/span&gt;:localhost:9229 user@remote_hostname_or_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will forward any TCP connections directed to your local 9229 port to the same port on the host.&lt;/p&gt;

&lt;p&gt;3) If everything is fine, now you can debug your remote app the same way as the local one. Just put this line to your URL bar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome://inspect/#devices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following page will be presented to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsood2o247t3xf5ye3q92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsood2o247t3xf5ye3q92.png" alt="Screenshot showing Chrome's interface for inspecting devices"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) Just click on the inspect &lt;/p&gt;

&lt;p&gt;5) Hunt the bugs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgs.xkcd.com%2Fcomics%2Fdebugging.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgs.xkcd.com%2Fcomics%2Fdebugging.png" alt="A comic from XKCD where the programmer tells a story to his friend, that after a long debugging session found the sword of Martin the warrior, his friend assumes that he switched the puzzles in his story"&gt;&lt;/a&gt;&lt;br&gt;
image source: &lt;a href="https://xkcd.com/" rel="noopener noreferrer"&gt;xkcd comic&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>network</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Bypassing the DNS hierarchy with the dig command</title>
      <dc:creator>Attila Molnar</dc:creator>
      <pubDate>Thu, 11 Jan 2018 14:05:09 +0000</pubDate>
      <link>https://dev.to/attilavm/exploring-dns-concepts-using-the-dig-command-4em</link>
      <guid>https://dev.to/attilavm/exploring-dns-concepts-using-the-dig-command-4em</guid>
      <description>&lt;h3&gt;
  
  
  Topics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Temporarily switching domain name servers (NS from now).&lt;/li&gt;
&lt;li&gt;Tracing domain name resolutions.&lt;/li&gt;
&lt;li&gt;Finding a way to interrogate NS directly, bypassing the DNS hierarchy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  First Use case
&lt;/h3&gt;

&lt;p&gt;You change your name server settings at your domain name registrar, but you do not see the effect immediately, lets say this problem emerges from the capability of your resolving NS of choice to cache domain name &amp;lt;--&amp;gt; IP (or other raw record) mappings.&lt;sup&gt;1&lt;/sup&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;Instead of temporarily changing the name server settings on your whole system, you can use the &lt;code&gt;dig&lt;/code&gt; command to override the name server for one request. The super power of &lt;code&gt;dig&lt;/code&gt; is that it mimics NS requests.&lt;/p&gt;

&lt;p&gt;synopsis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig &lt;span class="o"&gt;[&lt;/span&gt;@address of the NS] &lt;span class="o"&gt;[&lt;/span&gt;domain name] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig @208.67.222.222 wikipedia.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @208.67.222.222 wikipedia.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 4381
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;wikipedia.org.                 IN      A

;; ANSWER SECTION:
wikipedia.org.          600     IN      A       91.198.174.192

;; Query time: 75 msec
;; SERVER: 208.67.222.222#53(208.67.222.222)
;; WHEN: Thu Jan 11 11:43:32 CET 2018
;; MSG SIZE  rcvd: 58

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are interested only in the resulting IPs and raw data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig +noall +answer @208.67.222.222 github.io | rev | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 1 | rev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;151.101.1.147
151.101.65.147
151.101.129.147
151.101.193.147
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Second Use case
&lt;/h3&gt;

&lt;p&gt;Similarly to the first case the domain name &amp;lt;--&amp;gt; IP mapping is cached but not by the resolving NS, rather some other NS in its delegation chain.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution
&lt;/h4&gt;

&lt;p&gt;We will use some other neat features of &lt;code&gt;dig&lt;/code&gt;, first we will trace how our query is delegated in the NS hierarchy, then bypass this hierarchy.&lt;/p&gt;

&lt;p&gt;Usual hierarchy:&lt;br&gt;
 resolving NS --&amp;gt; Root NS --&amp;gt; TLD NS --&amp;gt; registry operator NS --&amp;gt; NS of a company.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig +trace @208.67.222.222 en.wikipedia.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; +trace @208.67.222.222 en.wikipedia.org
; (1 server found)
;; global options: +cmd
.                       518400  IN      NS      a.root-servers.net.
.                       518400  IN      NS      b.root-servers.net.
.                       518400  IN      NS      c.root-servers.net.
.                       518400  IN      NS      d.root-servers.net.
.                       518400  IN      NS      e.root-servers.net.
.                       518400  IN      NS      f.root-servers.net.
.                       518400  IN      NS      g.root-servers.net.
.                       518400  IN      NS      h.root-servers.net.
.                       518400  IN      NS      i.root-servers.net.
.                       518400  IN      NS      j.root-servers.net.
.                       518400  IN      NS      k.root-servers.net.
.                       518400  IN      NS      l.root-servers.net.
.                       518400  IN      NS      m.root-servers.net.
;; Received 239 bytes from 208.67.222.222#53(208.67.222.222) in 63 ms

org.                    172800  IN      NS      a2.org.afilias-nst.info.
org.                    172800  IN      NS      b0.org.afilias-nst.org.
org.                    172800  IN      NS      b2.org.afilias-nst.org.
org.                    172800  IN      NS      c0.org.afilias-nst.info.
org.                    172800  IN      NS      d0.org.afilias-nst.org.
org.                    172800  IN      NS      a0.org.afilias-nst.info.
org.                    86400   IN      DS      9795 7 2 3922B31B6F3A4EA92B19EB7B52120F031FD8E05FF0B03BAFCF9F891B FE7FF8E5
org.                    86400   IN      DS      9795 7 1 364DFAB3DAF254CAB477B5675B10766DDAA24982
org.                    86400   IN      RRSIG   DS 8 1 86400 20180124050000 20180111040000 41824 . BCA4iv0QFRRxn9WDpnUvHcuI7AnIMMuq/RhfnkyaSEA+XnYrcxHx2Tom UJDobnWucc5pDI/wLzdNFGP37VYUIfHKlnY8Fv9yFDWA5/nP2Wtdi591 SNrNFSmS+XXCwWIOMl7r6coouzGY1MRkmVXnbLjwN5FqvLqquAwFBWpa a5flfMnO7K5M2trNhYXUTo2BVB/ZnWNox+ynPjJB1xspkfS/K4Fv0BXx S6i6LMQk/rYEo4RIB/2JzPj+GWLTTSqD/LtQSA6f6kFFnDkywBSWSuBq hBGAxyrP0LWYbNuUBn8gP9H1kiWgcn8sgaHbcQlk4uKs9snB55myTQYw 7KLIUg==
;; Received 818 bytes from 192.33.4.12#53(c.root-servers.net) in 36 ms

wikipedia.org.          86400   IN      NS      ns0.wikimedia.org.
wikipedia.org.          86400   IN      NS      ns2.wikimedia.org.
wikipedia.org.          86400   IN      NS      ns1.wikimedia.org.
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86400 IN NSEC3 1 1 1 D399EAAB H9PARR669T6U8O1GSG9E1LMITK4DEM0T  NS SOA RRSIG DNSKEY NSEC3PARAM
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86400 IN RRSIG NSEC3 7 2 86400 20180201111010 20180111101010 1862 org. A3vUwzoJIFJbiWgQK1/ACwB6ZyvIK99ulaAJAoalHwrKn1JnecZ7Sina rEhvKs4vL+FWLvwLNfDWthfaFsO0++eaVFFQ3A6tWvx8PQk2nSKsGdEI Ri6Nld7lJIkL3DCo0PY+0+WwJFnhUGXTtr+B0uPSGA+jSBsQWYTmJnQI 2dM=
hhdfcaa81hb1nfs0h6sd0pq6ctib1781.org. 86400 IN NSEC3 1 1 1 D399EAAB HHE2JLM2DDBRLOQF1RVBUAGVETJ6EPFD 
hhdfcaa81hb1nfs0h6sd0pq6ctib1781.org. 86400 IN RRSIG NSEC3 7 2 86400 20180130153401 20180109143401 1862 org. YK0/K+mWIph03k8zsmD90XnmsxU2bdm60usXSMR8QnbsS4aJpmzGvGOQ FZOnOuUAv58++rtlXU5SI0cQ5vZ0L/iTGW3iXlD9WBQoa/e45E7vtzbK Kn2fhMSLVLWzn377i8AWOgpC4LNHPKIyA1o1NRtdvxkhASNbY5PQWaQI oN8=
;; Received 642 bytes from 199.19.56.1#53(a0.org.afilias-nst.info) in 299 ms

en.wikipedia.org.       600     IN      A       91.198.174.192
;; Received 89 bytes from 91.198.174.239#53(ns2.wikimedia.org) in 52 ms


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every table is a response from a different NS. The columns are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The domain name to look up&lt;/li&gt;
&lt;li&gt;The time-to-live value [ seconds ] how much time the requester should cache this result.&lt;/li&gt;
&lt;li&gt;The Class of the network where the domain name is mapped, which is almost always the internet &lt;code&gt;IN&lt;/code&gt;. If you see something like &lt;a href="https://en.wikipedia.org/wiki/Chaosnet"&gt;CH&lt;/a&gt;, then you will meet history itself.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/List_of_DNS_record_types"&gt;Type of the record&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The raw data of the record, like the IP address. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most important lines for us have this form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;;; Received [number] bytes from [address]#[port](domain name) in [milliseconds] ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;;; Received 89 bytes from 91.198.174.239#53(ns2.wikimedia.org) in 52 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They expose the address and port of the name server, which we can use to bypass the name resolution hierarchy, which can be useful to identify caching issues.&lt;/p&gt;

&lt;p&gt;Applying this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig &lt;span class="nt"&gt;-p&lt;/span&gt; 53 @208.80.154.238 en.wikipedia.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; -p 53 @208.80.154.238 en.wikipedia.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 31772
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1024
;; QUESTION SECTION:
;en.wikipedia.org.              IN      A

;; ANSWER SECTION:
en.wikipedia.org.       600     IN      A       91.198.174.192

;; ADDITIONAL SECTION:
en.wikipedia.org.       600     IN      AAAA    2620:0:862:ed1a::1

;; Query time: 135 msec
;; SERVER: 208.80.154.238#53(208.80.154.238)
;; WHEN: Thu Jan 11 13:55:53 CET 2018
;; MSG SIZE  rcvd: 89

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used the &lt;code&gt;-p&lt;/code&gt; switch to set the port explicitly, however 53 is the default port for domain name requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Linux
&lt;/h4&gt;

&lt;p&gt;It is almost always provided by your default package manager or use &lt;a href="https://nixos.org/nix/"&gt;Nix&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  MacOS
&lt;/h4&gt;

&lt;p&gt;You can use &lt;a href="https://www.macports.org/"&gt;MacPorts&lt;/a&gt;, &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; or Nix.&lt;/p&gt;

&lt;h4&gt;
  
  
  Windows
&lt;/h4&gt;

&lt;p&gt;As Jack Fletcher pointed out in the discussion you can use &lt;a href="https://chocolatey.org/"&gt;Chocolatey&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Online
&lt;/h4&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/nslookuptool"&gt;@nslookuptool&lt;/a&gt;
 shared a link to a nice &lt;a href="https://www.diggui.com/"&gt;web interface&lt;/a&gt; for &lt;code&gt;dig&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further reading
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/an-introduction-to-dns-terminology-components-and-concepts"&gt;Conceptual introduction for DNS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://blog.dnsimple.com/2015/03/whats-in-a-dns-response/"&gt;What's in a DNS response?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this post provides others a new aspect how the Domain Name System works.&lt;/p&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;p&gt;&lt;a&gt;1.&lt;/a&gt; Your browser is also capable to cache domain names, as well as your OS. Windows and MacOS do this by default, on Linux you can install and configure &lt;a href="https://www.g-loaded.eu/2010/09/18/caching-nameserver-using-dnsmasq/"&gt;dnsmasq&lt;/a&gt; but you shouldn't, since your browser is caching domain names for you. I would even disable OS level DNS caching if I had one running.&lt;/p&gt;

</description>
      <category>dns</category>
      <category>network</category>
      <category>cli</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
