<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Karnsonline]]></title><description><![CDATA[Karnsonline]]></description><link>https://karnsonline.com/</link><image><url>https://karnsonline.com/favicon.png</url><title>Karnsonline</title><link>https://karnsonline.com/</link></image><generator>Ghost 5.87</generator><lastBuildDate>Tue, 07 Apr 2026 22:13:16 GMT</lastBuildDate><atom:link href="https://karnsonline.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Download ALL photos from Amazon Photos]]></title><description><![CDATA[Provided is a Javascript snippet that can be used to download all your photos without any size or count limitations. You can just plop this in your web console and let it run.]]></description><link>https://karnsonline.com/download-all-photos-from-amazon-photos/</link><guid isPermaLink="false">6939d0a76c47730001e523f5</guid><category><![CDATA[Amazon Photos]]></category><category><![CDATA[javascript]]></category><category><![CDATA[Download]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Wed, 10 Dec 2025 20:14:03 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1612681336352-b8b82f3c775a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE3fHxwaG90byUyMHN0YWNrfGVufDB8fHx8MTc2NTM5NzM5MXww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1612681336352-b8b82f3c775a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE3fHxwaG90byUyMHN0YWNrfGVufDB8fHx8MTc2NTM5NzM5MXww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="Download ALL photos from Amazon Photos"><p>It&apos;s kind of unbelievable that Amazon is forcing their customers into a vendor lock and not allowing them an easy or straightforward way to download <code>ALL</code> of their photos in bulk.</p>
<p>The explanation is simple. They don&apos;t want you go to another service and lose the revenue. It would certainly appear that their bottom line is more important to them than the customers rights.</p>
<p>Provided is a Javascript snippet that can be used to download all your photos without any size or count limitations. You can just plop this in your web console and let it run.</p>
<blockquote>
<p><a href="https://developer.chrome.com/docs/devtools/open?ref=karnsonline.com">How do I open the chrome web console?</a></p>
</blockquote>
<p>However, since this is running serially, it will take some time. there are timeouts in the script and waiters for elements to be visible before downloading the image to help make the process more reliable and prevent photos from being skipped.</p>
<h3 id="bonus">Bonus</h3>
<p>This script will allow you to delete the photos from Amazon Photos after they have been downloaded. Just set the varible to <code>true</code> at the bottom of the script before running.</p>
<pre><code>// Set to true to delete files after downloading
const deleteFiles = true;
</code></pre>
<h2 id="lets-go">Let&apos;s go!</h2>
<ul>
<li>Open amazon photos in chrome</li>
<li>Select the first photo so you can see it in a &quot;slide show&quot;</li>
<li>Open the web console</li>
<li>Paste the entire code snippet</li>
<li>Press Enter</li>
<li>Wait</li>
<li>Profit</li>
</ul>
<pre><code class="language-javascript">function waitForElement(selector, timeout = 100) {
  return new Promise((resolve, reject) =&gt; {
    const startTime = Date.now();

    const checkElement = () =&gt; {
      const element = document.querySelector(selector);
      if (element) {
        resolve(element);
      } else if (Date.now() - startTime &gt; timeout) {
        reject(new Error(`Element ${selector} not found within ${timeout}ms`));
      } else {
        setTimeout(checkElement, 100);
      }
    };

    checkElement();
  });
}

function sleep(ms) {
  return new Promise(resolve =&gt; setTimeout(resolve, ms));
}

async function run(deleteFiles=false) {
  let downloadCount = 0;

  try {
    // Click the Information button at the beginning
    const spans = document.querySelectorAll(&apos;#main-content &gt; section &gt; header &gt; ul &gt; li &gt; button &gt; span.label&apos;);
    const infoButton = Array.from(spans).find(span =&gt; span.textContent.trim() === &apos;Information&apos;);
    if (infoButton) {
      infoButton.closest(&apos;button&apos;).click();
      console.log(&apos;Clicked Information button&apos;);
      await sleep(500);
    }

    while (true) {
      await ensureAsideVisible();
      await clickMainContentButton();
      await waitForElement(&apos;button.download[title=&quot;Download&quot;]&apos;);
      await clickDownloadButton(++downloadCount);
      await sleep(1200); // Wait for download to start

      if (deleteFiles) {
        await clickDeleteButton();
        await confirmDelete();
        await sleep(500);
      }

      const hasNext = await clickNextButton();
      if (!hasNext) {
        break;
      }
      await waitForElement(&apos;#main-content &gt; section &gt; header &gt; div &gt; button&apos;);
    }

    console.log(`Finished downloading ${downloadCount} files`);
  } catch (error) {
    console.error(`Script stopped: ${error.message}`);
    console.log(`Total files downloaded before stopping: ${downloadCount}`);
  }
}

async function ensureAsideVisible() {
  const aside = document.querySelector(&apos;#main-content &gt; section &gt; aside&apos;);
  if (!aside || window.getComputedStyle(aside).display === &apos;none&apos; || !aside.offsetParent) {
    const button = document.querySelector(&apos;#main-content &gt; section &gt; header &gt; div &gt; button&apos;);
    if (button) {
      button.click();
      await sleep(300);
      console.log(&apos;Opened aside panel&apos;);
    }
  }
}

function clickMainContentButton() {
  const button = document.querySelector(&apos;#main-content &gt; section &gt; header &gt; div &gt; button&apos;);
  if (button) {
    button.click();
  }
}

function clickDownloadButton(count) {
  const downloadButton = document.querySelector(&apos;button.download[title=&quot;Download&quot;]&apos;);
  if (!downloadButton) {
    throw new Error(&apos;Download button not found&apos;);
  }
  const fileInfoDiv = document.querySelector(&apos;.detail-item.file-info&apos;);
  const imageName = fileInfoDiv ? fileInfoDiv.querySelector(&apos;span.label&apos;).innerText : &apos;unknown&apos;;
  downloadButton.click();
  console.log(`Downloading file ${count} - ${imageName}`);
}

function clickDeleteButton() {
  const deleteButton = document.querySelector(&apos;button.trash&apos;);
  if (!deleteButton) {
    throw new Error(&apos;Delete button (button.trash) not found&apos;);
  }
  deleteButton.click();
  console.log(&apos;Opened delete modal&apos;);
}

async function confirmDelete() {
  // Wait for the delete dialog to appear
  await waitForElement(&apos;aside.TrashConfirm&apos;, 5000);
  // Wait for the delete confirmation button to be visible
  await waitForElement(&apos;button[aria-label=&quot;Delete&quot;]&apos;, 5000);
  const confirmButton = document.querySelector(&apos;button[aria-label=&quot;Delete&quot;]&apos;);
  if (!confirmButton) {
    throw new Error(&apos;Delete confirmation button not found&apos;);
  }
  confirmButton.click();
  console.log(&apos;Confirmed delete&apos;);
  // Wait for the dialog to close and action to complete
  await sleep(500);
}

async function clickNextButton() {
  try {
    await waitForElement(&apos;.image-and-controls .next&apos;, 3000);
    const nextButton = document.querySelector(&apos;.image-and-controls .next&apos;);
    if (nextButton) {
      nextButton.click();
      return true;
    }
  } catch (error) {
    console.log(&apos;No next button found - reached end of album&apos;);
  }
  return false;
}

// Set to true to delete files after downloading
const deleteFiles = true;

// Start the script
run(deleteFiles);

</code></pre>
]]></content:encoded></item><item><title><![CDATA[2025-1-9]]></title><description><![CDATA[<figure class="kg-card kg-embed-card"><iframe style="border-radius: 12px" width="100%" height="352" title="Spotify Embed: ThE=mc2 Periodic Rotator" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy" src="https://open.spotify.com/embed/playlist/0UbyWdRhUhRNDw4i8lnH53?si=9399cd6a1ad24695&amp;utm_source=oembed"></iframe></figure>]]></description><link>https://karnsonline.com/2025-1-9/</link><guid isPermaLink="false">6780285bfebd7d0001f5adc9</guid><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Thu, 09 Jan 2025 19:51:30 GMT</pubDate><media:content url="https://karnsonline.com/content/images/2025/01/spotify-archive-HERO.png" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-embed-card"><iframe style="border-radius: 12px" width="100%" height="352" title="Spotify Embed: ThE=mc2 Periodic Rotator" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy" src="https://open.spotify.com/embed/playlist/0UbyWdRhUhRNDw4i8lnH53?si=9399cd6a1ad24695&amp;utm_source=oembed"></iframe></figure>]]></content:encoded></item><item><title><![CDATA[Git diff hide package-lock files]]></title><description><![CDATA[Do you really need to see a billion lines of diff in a package-lock.json file? I know I rarely benefit from seeing the diff. Wouldn't it be great if those were just collapsed when you run git diff in the terminal? Lets make it happen.]]></description><link>https://karnsonline.com/git-diff-hide-package-lock-files/</link><guid isPermaLink="false">6751d8e5febd7d0001f5ad95</guid><category><![CDATA[git]]></category><category><![CDATA[terminal]]></category><category><![CDATA[bash]]></category><category><![CDATA[coding]]></category><category><![CDATA[linux]]></category><category><![CDATA[mac]]></category><category><![CDATA[macOs]]></category><category><![CDATA[osx]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Thu, 05 Dec 2024 17:17:31 GMT</pubDate><media:content url="https://karnsonline.com/content/images/2024/12/Screenshot-2024-12-05-at-12.11.33-PM.png" medium="image"/><content:encoded><![CDATA[<img src="https://karnsonline.com/content/images/2024/12/Screenshot-2024-12-05-at-12.11.33-PM.png" alt="Git diff hide package-lock files"><p>Do you really need to see a billion lines of diff in a `package-lock.json` file? I know I rarely benefit from seeing the diff. Wouldn&apos;t it be great if those were just collapsed when you run <code>git diff</code> in the terminal? Lets make it happen.</p><h3 id="create-a-gitattributes-file">Create a .gitattributes file</h3><pre><code>touch ~/.gitattributes</code></pre><h3 id="add-content-to-the-file">Add Content to the file</h3><p>Add the following lines the file to collapse package-lock.json files from diffs.</p><pre><code># Exclude package-lock from git diff
**/package-lock.json -diff</code></pre><h3 id="configure-git-to-use-the-new-configuration">Configure Git to use the new configuration</h3><p>Tell Git to use the new <code>.gitattributes</code> file</p><pre><code>git&#xA0;config&#xA0;--global&#xA0;core.attributesFile&#xA0;&quot;~/.gitattributes&quot;</code></pre>]]></content:encoded></item><item><title><![CDATA[Temporarily disable PiHole blocking with Apple shortcut]]></title><description><![CDATA[You may want to disable your PiHole ad blocking momentarily to open a link. Wouldn't it be great to disable ad blocking from your Apple Watch or iPhone?]]></description><link>https://karnsonline.com/temporarily-disable-pihole-blocking-with-apple-shortcut/</link><guid isPermaLink="false">67167461febd7d0001f5aceb</guid><category><![CDATA[pihole]]></category><category><![CDATA[apple]]></category><category><![CDATA[shortcuts]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Mon, 21 Oct 2024 16:38:22 GMT</pubDate><media:content url="https://karnsonline.com/content/images/2024/10/pihole-shortcuts-1.png" medium="image"/><content:encoded><![CDATA[<h3 id="the-problem">The Problem: </h3><img src="https://karnsonline.com/content/images/2024/10/pihole-shortcuts-1.png" alt="Temporarily disable PiHole blocking with Apple shortcut"><p>Its a typical situation where you may want to disable your PiHole ad blocking momentarily to open a link. To increase the wife appreciation factor, this needs to be a task that can be accomplished as easily as possible. Don&apos;t get me wrong, the PiHole UI is great and this task can be accomplished there pretty easily, but wouldn&apos;t it be great to trigger this action from my Apple Watch or iPhone?</p><h3 id="the-solution">The Solution:</h3><p>Build an Apple shortcut that has options to disable ad blocking for 10 seconds, 30 seconds and 5 minutes that can be ran on an Apple Watch, iPad, iPhone, etc.</p><h3 id="assumptions">Assumptions:</h3><blockquote>This solution is intended to be used with PiHole &gt;= 6. IT IS NOT compatible with PiHole 5.</blockquote><ul><li>You have an <code>app password</code> which is used as your <code>API KEY</code></li></ul><blockquote>Tbe <code>app password</code> can be created a the following route: <a href="http://pihole.local.io/admin/settings/api?ref=karnsonline.com">/admin/settings/api</a></blockquote><h2 id="the-shortcut">The Shortcut</h2><h4 id="global-variables">Global Variables:</h4><p>We need to set some variables for our shortcut to use</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2024/10/pihole_shortcut_variables-1.png" class="kg-image" alt="Temporarily disable PiHole blocking with Apple shortcut" loading="lazy" width="621" height="324" srcset="https://karnsonline.com/content/images/size/w600/2024/10/pihole_shortcut_variables-1.png 600w, https://karnsonline.com/content/images/2024/10/pihole_shortcut_variables-1.png 621w"></figure><h4 id="select-disable-time">Select Disable Time:</h4><p>Allow the user to select how long to disable ad blocking</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2024/10/pihole_shortcut_selection.png" class="kg-image" alt="Temporarily disable PiHole blocking with Apple shortcut" loading="lazy" width="620" height="823" srcset="https://karnsonline.com/content/images/size/w600/2024/10/pihole_shortcut_selection.png 600w, https://karnsonline.com/content/images/2024/10/pihole_shortcut_selection.png 620w"></figure><h4 id="authenticate">Authenticate:</h4><p>Authenticate and get a session ID (sid) to be used with our API requests</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2024/10/pihole_shortcut_auth.png" class="kg-image" alt="Temporarily disable PiHole blocking with Apple shortcut" loading="lazy" width="614" height="507" srcset="https://karnsonline.com/content/images/size/w600/2024/10/pihole_shortcut_auth.png 600w, https://karnsonline.com/content/images/2024/10/pihole_shortcut_auth.png 614w"></figure><h4 id="store-authentication-session-id">Store Authentication Session ID:</h4><p>By clicking the <code>Set variable</code> we need to specify the key that contains our session ID. in this case we set the <code>Get Value for Key</code> to <code>session.id</code></p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2024/10/pihole_shortcut_auth_data.png" class="kg-image" alt="Temporarily disable PiHole blocking with Apple shortcut" loading="lazy" width="345" height="418"></figure><h4 id="disable-ad-blocking">Disable Ad Blocking:</h4><p>Make the <code>POST</code> request to the API to disable ad blocking</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2024/10/pihole_shortcut_disable.png" class="kg-image" alt="Temporarily disable PiHole blocking with Apple shortcut" loading="lazy" width="615" height="399" srcset="https://karnsonline.com/content/images/size/w600/2024/10/pihole_shortcut_disable.png 600w, https://karnsonline.com/content/images/2024/10/pihole_shortcut_disable.png 615w"></figure><h4 id="delete-authentication-session">Delete Authentication Session:</h4><p>We need to clean up after ourselves each time because by default PiHole is set up to allow 10 sessions. You could increase this number but it seems more responsible to delete our session ID when we are done.</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2024/10/pihole_shortcut_auth_cleanup.png" class="kg-image" alt="Temporarily disable PiHole blocking with Apple shortcut" loading="lazy" width="614" height="402" srcset="https://karnsonline.com/content/images/size/w600/2024/10/pihole_shortcut_auth_cleanup.png 600w, https://karnsonline.com/content/images/2024/10/pihole_shortcut_auth_cleanup.png 614w"></figure>]]></content:encoded></item><item><title><![CDATA[Affiliate Links]]></title><description><![CDATA[<div class="kg-card kg-product-card">
            <div class="kg-product-card-container">
                <img src="https://karnsonline.com/content/images/2024/10/solis_hotspot.jpg" width="1498" height="1496" class="kg-product-card-image" loading="lazy">
                <div class="kg-product-card-title-container">
                    <h4 class="kg-product-card-title"><span style="white-space: pre-wrap;">solis wifi</span></h4>
                </div>
                
                    <div class="kg-product-card-rating">
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                    </div>
                

                <div class="kg-product-card-description"><p dir="ltr"><span style="white-space: pre-wrap;">The best contract free international hotspot</span></p></div>
                
                    <a href="https://amzn.to/3U2sjzL?ref=karnsonline.com" class="kg-product-card-button kg-product-card-btn-accent" target="_blank" rel="noopener noreferrer"><span>Amazon</span></a>
                
            </div>
        </div>]]></description><link>https://karnsonline.com/affiliate-links/</link><guid isPermaLink="false">6707f43dfebd7d0001f5acca</guid><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Thu, 10 Oct 2024 15:41:22 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card kg-product-card">
            <div class="kg-product-card-container">
                <img src="https://karnsonline.com/content/images/2024/10/solis_hotspot.jpg" width="1498" height="1496" class="kg-product-card-image" loading="lazy">
                <div class="kg-product-card-title-container">
                    <h4 class="kg-product-card-title"><span style="white-space: pre-wrap;">solis wifi</span></h4>
                </div>
                
                    <div class="kg-product-card-rating">
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                        <span class="kg-product-card-rating-active kg-product-card-rating-star"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M12.729,1.2l3.346,6.629,6.44.638a.805.805,0,0,1,.5,1.374l-5.3,5.253,1.965,7.138a.813.813,0,0,1-1.151.935L12,19.934,5.48,23.163a.813.813,0,0,1-1.151-.935L6.294,15.09.99,9.837a.805.805,0,0,1,.5-1.374l6.44-.638L11.271,1.2A.819.819,0,0,1,12.729,1.2Z"/></svg></span>
                    </div>
                

                <div class="kg-product-card-description"><p dir="ltr"><span style="white-space: pre-wrap;">The best contract free international hotspot</span></p></div>
                
                    <a href="https://amzn.to/3U2sjzL?ref=karnsonline.com" class="kg-product-card-button kg-product-card-btn-accent" target="_blank" rel="noopener noreferrer"><span>Amazon</span></a>
                
            </div>
        </div>]]></content:encoded></item><item><title><![CDATA[Helm Secret Juggling]]></title><description><![CDATA[<p>This solution requires a values file with the following schema. Notice how each component is in <code>components</code>. The best part of this is that if there is no <code>secrets</code> property in the component, it will skip the secrets template.</p><p>If no value is provided by setting it via the command</p>]]></description><link>https://karnsonline.com/helm-secret-juggling/</link><guid isPermaLink="false">66917d29bfcedb0001419100</guid><category><![CDATA[kubernetes]]></category><category><![CDATA[helm]]></category><category><![CDATA[secrets]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Fri, 12 Jul 2024 19:17:42 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1674606867357-a9b26fbdca9e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI0fHxoZWxtfGVufDB8fHx8MTcyMDgxMTc1MXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1674606867357-a9b26fbdca9e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI0fHxoZWxtfGVufDB8fHx8MTcyMDgxMTc1MXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Helm Secret Juggling"><p>This solution requires a values file with the following schema. Notice how each component is in <code>components</code>. The best part of this is that if there is no <code>secrets</code> property in the component, it will skip the secrets template.</p><p>If no value is provided by setting it via the command line and it has a value already set, it will use the current value in the secret.</p><p>All secrets will be initialized with the value of <code>initial</code> unless they are specifically provided on <code>install</code> or <code>upgrade</code> like so.</p><pre><code class="language-bash">helm upgrade juggle ./chart_directory -n juggle \
  --set components.second.secrets.SUPER_SECRET=&quot;string&quot;</code></pre><pre><code class="language-yaml">## values.yaml ##

components:
  first:
    name: first component

  second:
    name: second component

    secrets:
      SUPER_SECRET: null 
      ANOTHER_SECRET: null
</code></pre><pre><code class="language-yaml">## secrets.yaml ##

{{- range $system, $settings := .Values.components -}}
{{ if $settings.secrets }}
{{ include &quot;system.secrets.component&quot;  (dict &quot;component&quot; $settings &quot;values&quot; $.Values &quot;release&quot; $.Release) }}
{{- end }}
{{- end }}</code></pre><pre><code class="language-helm">## _secrets.tpl ##

{{/*
Secret initializer and data maintainer
This helper will initialize the secret data with &quot;initial&quot; value if the secret is not found in the secret object.
IF the secret is found in the secret object, it will use the set value from the secret object thereby maintaining the secret data.
*/}}
{{- define &quot;helper.secrets&quot; -}}
  {{- $secretObj := (lookup &quot;v1&quot; &quot;Secret&quot; .release.Namespace .component.name) | default dict }}
  {{- range $key, $value := .component.secrets }}
  {{- if empty $value -}}
  {{- $secretData := (get $secretObj &quot;data&quot;) | default dict }}
  {{- $secret := (get $secretData $key) | default (&quot;initial&quot; | b64enc) }}
  {{ $key }}: {{ $secret | quote }}
  {{- else }}
  {{ $key }}: {{ $value | b64enc | quote }}
  {{- end -}}
  {{- end }}
{{- end -}}

{{- define &quot;system.secrets.component&quot; }}

---
apiVersion: v1
kind: Secret
metadata:
  name: {{ .component.name }}
  labels:
{{ include &quot;helper.metaLabels&quot; . | indent 4 }}
type: Opaque
data:
{{ include &quot;helper.secrets&quot; . | indent 2 }}
{{- end }}
</code></pre><h2 id="troubleshooting">Troubleshooting</h2><p>In order to really test this during a ` Dry Run` you need to make sure you tweak your option so helm has access to the server data at run time.</p><pre><code>--dry-run=server</code></pre>]]></content:encoded></item><item><title><![CDATA[Kubectl config helpers]]></title><description><![CDATA[If you manage multiple k8s clusters you have no doubt tinkered with different ways to store and use the config files.]]></description><link>https://karnsonline.com/kubectl-config-helpers/</link><guid isPermaLink="false">6644ea2aa4a3d8000187f411</guid><category><![CDATA[kubernetes]]></category><category><![CDATA[k9s]]></category><category><![CDATA[automation]]></category><category><![CDATA[bash]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Wed, 15 May 2024 17:18:35 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1667372459534-848ec00d4da7?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDd8fGs4c3xlbnwwfHx8fDE3MTU3OTI1MDR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1667372459534-848ec00d4da7?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDd8fGs4c3xlbnwwfHx8fDE3MTU3OTI1MDR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Kubectl config helpers"><p>If you manage multiple k8s clusters you have no doubt tinkered with different ways to store and use the config files.</p><p>Below is my preferred method of wrangling them and how I switch between them effectively.</p><p>In my <code>~/.kube</code> directory I have individual configs for each cluster and a <code>config</code> file with null values. This <code>config</code> file with null values is used as a placeholder and gets updated when the<code>current-context</code> changes. This is preferable to having the current context updated in a seemingly random config file.</p><p>~/.kube/config</p>
<pre><code class="language-yaml">apiVersion: v1
clusters: null
contexts: null
current-context: Trowbridge-k0s
kind: Config
preferences: {}
users: null
</code></pre>
<p>Your individual cluster configs will reside in the <code>~/.kube</code> directory as well and will have a filename prefix of <code>config</code></p><p>~/.kube/config-example</p>
<pre><code>apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: somesupersecretstring
    server: https://example.com:16443
  name: Example
contexts:
- context:
    cluster: Example
    user: Example
  name: Example
kind: Config
preferences: {}
users:
- name: Example
  user:
    token: somesupersecretstring
</code></pre>
<blockquote>
<p>Notice the example config does not have a <code>current-context</code> line</p>
</blockquote>
<p>For this to work you will need to make a slight modification to your terminal profile. <code>.bash_profile</code> / <code>.bashrc</code> / etc.</p><pre><code class="language-shell"># load all the config files in the .kube directory
export KUBECONFIG=$(find ~/.kube -name &apos;config*&apos; | sort | tr &apos;\n&apos; &apos;:&apos;)
</code></pre>
<p>This line is iterating over the <code>~/.kube</code> directory and grabbing files that begin with <code>config</code> and sorting them so that the <code>config</code> proper file is loaded first.</p><p>With that, kubectl has access to all your configs and they are nicely separated and easy to work with.</p><h2 id="helper-script">Helper Script</h2>
<p>Add the following either as a bash function in your profile or as a shell script that is linked to an alias to make context switching a breeze.</p>
<p>ktx.sh</p>
<pre><code class="language-bash">#!/usr/bin/env bash

red=$(tput setaf 1)
gold=$(tput setaf 3)
blue=$(tput setaf 4)
magenta=$(tput setaf 5)
cyan=$(tput setaf 6)
default=$(tput sgr0)

# ensure kubectl is installed
if ! hash kubectl 2&gt;/dev/null
then
  echo &quot;${red}You need kubectl installed${default}&quot;
  exit 0
fi

CONTEXTS=( $(kubectl config get-contexts | awk &apos;NR!=1&apos;&apos;{print $2}&apos;) )

PS3=&quot;${cyan}Select a kubectl context (q to quit): $gold&quot;
select context in &quot;${CONTEXTS[@]}&quot;; do
  case &quot;$context&quot; in
    &quot;&quot;) break ;;  # This is a fake; any invalid entry makes $context==&quot;&quot;, not just &quot;q&quot;.
    *) break ;;
  esac
done


if [ ! -z &quot;$context&quot; ]
then
  kubectl config use-context $context &gt; /dev/null
  echo &quot;${blue}Kubectl Context switched to [${magenta}$context${default}]&quot;
fi
</code></pre>
]]></content:encoded></item><item><title><![CDATA[kubernetes cheat sheet]]></title><description><![CDATA[<p>Update an env variable in a running pod</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl set env deployment &lt;deployment_name&gt; &lt;VAR_NAME&gt;=false -n &lt;namespace&gt;
</code></pre>
<!--kg-card-end: markdown--><p>Remove an env variable from a running deployment (note the <code>-</code> after the VAR_NAME)</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl set env deployment &lt;deployment_name&gt; &lt;VAR_</code></pre>]]></description><link>https://karnsonline.com/kubernetes-cheat-sheet/</link><guid isPermaLink="false">66393ede5fb63a0001e86a70</guid><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Thu, 04 May 2023 13:49:28 GMT</pubDate><content:encoded><![CDATA[<p>Update an env variable in a running pod</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl set env deployment &lt;deployment_name&gt; &lt;VAR_NAME&gt;=false -n &lt;namespace&gt;
</code></pre>
<!--kg-card-end: markdown--><p>Remove an env variable from a running deployment (note the <code>-</code> after the VAR_NAME)</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl set env deployment &lt;deployment_name&gt; &lt;VAR_NAME&gt;- -n &lt;namespace&gt;
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[2022-12-14]]></title><description><![CDATA[<figure class="kg-card kg-embed-card"><iframe style="border-radius: 12px" width="100%" height="380" title="Spotify Embed: 2012-12-14" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy" src="https://open.spotify.com/embed/playlist/1mM9AUc1tn6T6h5dvuXEun?si=09463894fa6242e0&amp;utm_source=oembed"></iframe></figure>]]></description><link>https://karnsonline.com/2022-12-14/</link><guid isPermaLink="false">66393ede5fb63a0001e86a6f</guid><category><![CDATA[periodic-rotator]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Wed, 14 Dec 2022 21:52:05 GMT</pubDate><media:content url="https://karnsonline.com/content/images/2022/12/spotify-archive-HERO-5.png" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-embed-card"><iframe style="border-radius: 12px" width="100%" height="380" title="Spotify Embed: 2012-12-14" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy" src="https://open.spotify.com/embed/playlist/1mM9AUc1tn6T6h5dvuXEun?si=09463894fa6242e0&amp;utm_source=oembed"></iframe></figure>]]></content:encoded></item><item><title><![CDATA[She Bang Bin Bash]]></title><description><![CDATA[<p>Apparently, Apple is being a big baby and not installing a modern version of bash on macOs any longer.</p><p>macOs is currently shipping with <code>bash version 3</code>. This is fine in most cases but what if you want to use some of the modern conveniences that come with bash &gt;</p>]]></description><link>https://karnsonline.com/she-bang-bin-bash/</link><guid isPermaLink="false">66393ede5fb63a0001e86a6e</guid><category><![CDATA[bash]]></category><category><![CDATA[macOs]]></category><category><![CDATA[linux]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Mon, 29 Aug 2022 20:29:36 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1629654297299-c8506221ca97?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGJhc2h8ZW58MHx8fHwxNjYxODA0ODcz&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1629654297299-c8506221ca97?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGJhc2h8ZW58MHx8fHwxNjYxODA0ODcz&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="She Bang Bin Bash"><p>Apparently, Apple is being a big baby and not installing a modern version of bash on macOs any longer.</p><p>macOs is currently shipping with <code>bash version 3</code>. This is fine in most cases but what if you want to use some of the modern conveniences that come with bash &gt;= 4? (like associative arrays).</p><p>we can do that by installing the latest version (version 5 at the time of this writing) using homebrew.</p><pre><code>brew install bash
brew link bash</code></pre><h2 id="the-catch">The Catch!</h2><p>we dont want to use the old version 3 binary that is still living on the machine so we can no longer use <code>#!/bin/bash</code> at the top of our bash scripts.</p><h2 id="the-solution">The Solution</h2><p>We have to get in the habit of using the users specified version of bash</p><pre><code>#!/usr/bin/env bash</code></pre><p>Additionally, I have been including a check for <code>bash &gt;= 4</code> in my scripts that use associative arrays like so:</p><pre><code class="language-shell"># Ensure bash version is greater than or equal to 4, so we can use associtative arrays
if [ &quot;${BASH_VERSINFO:-0}&quot; -le 4 ]
then  
	echo &quot;You need bash &gt;= 4&quot;
    exit 0
fi</code></pre>]]></content:encoded></item><item><title><![CDATA[Burn exif meta data to photos]]></title><description><![CDATA[<p>People always ask me &quot;what were your camera settings for that photo&quot;, so I wrote some bash functions to burn the relevant data to the bottom of the image.</p><p>The following bash functions assume a few things:</p><ul><li>you are on a Mac or Linux system</li><li>You know how</li></ul>]]></description><link>https://karnsonline.com/burn-exif-meta-data-to-photos/</link><guid isPermaLink="false">66393ede5fb63a0001e86a6d</guid><category><![CDATA[astrophotography]]></category><category><![CDATA[bash]]></category><category><![CDATA[coding]]></category><category><![CDATA[macOs]]></category><category><![CDATA[linux]]></category><category><![CDATA[ubuntu]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Fri, 05 Aug 2022 16:08:34 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1579260729526-ca1e77ad9092?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEwOXx8Y2FtZXJhfGVufDB8fHx8MTY1OTcxNTYzNw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1579260729526-ca1e77ad9092?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEwOXx8Y2FtZXJhfGVufDB8fHx8MTY1OTcxNTYzNw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Burn exif meta data to photos"><p>People always ask me &quot;what were your camera settings for that photo&quot;, so I wrote some bash functions to burn the relevant data to the bottom of the image.</p><p>The following bash functions assume a few things:</p><ul><li>you are on a Mac or Linux system</li><li>You know how to modify your <code>.bash_profile</code> (macOs) or <code>.bashrc</code> (Linux). We arent going to get into that here. For more info see <a href="https://linuxhint.com/simple-guide-to-create-open-edit-bash-profile/?ref=karnsonline.com">https://linuxhint.com/simple-guide-to-create-open-edit-bash-profile/</a></li><li>You have <code>exiftool</code> installed</li><li><code>brew install exiftool</code> (macOs)</li><li><code>apt install exiftool</code> (Linux)</li></ul><p>Once you have met the requirements, you just need to put the following functions in your appropriate profile.</p><!--kg-card-begin: markdown--><pre><code class="language-bash">function exifshort(){

  if hash exiftool 2&gt;/dev/null; then
    echo &quot;&quot;
  else
    if [ &quot;$(uname)&quot; == &quot;Darwin&quot; ]; then
      brew install exiftool
    elif [ &quot;$(expr substr $(uname -s) 1 5)&quot; == &quot;Linux&quot; ]; then
      sudo apt install exiftool
    fi
  fi

  FILE=$1
  if [ -z &quot;$FILE&quot; ];then
    echo &quot;${red}You must specify a file path${default}&quot;
    exit 1
  else
    MODEL=`exiftool -Model $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`
    ISO=`exiftool -ISO $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`
    LENS=`exiftool -LensModel $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`
    EXPOSURE=`exiftool -ExposureTime $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`
    DATE=`exiftool -CreateDate $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`
    APERTURE=`exiftool -ApertureValue $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`
    FOCAL_LENGTH=`exiftool -FocalLength $FILE | awk -F &apos;: &apos; &apos;{print $2}&apos;`

    echo &quot;$MODEL + $LENS @ $FOCAL_LENGTH, ISO $ISO, $EXPOSURE seconds, f/$APERTURE, $DATE&quot;
  fi
}
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code class="language-bash">function burnexif(){
  IN=$1
  PAD=100
  FONT_SIZE=32

  PATH_IN=$(readlink -f $IN)
  EXTENSION=${PATH_IN##*.}
  PATH_OUT=${PATH_IN%.*}-processed.${EXTENSION}

  echo -e &quot;\nProcessing:\n  $PATH_IN&quot;
  echo -e &quot;Output File:\n  $PATH_OUT&quot;

  ((LEFT=(0 + $PAD)))
  ((RIGHT=$(identify -format &apos;%w&apos; $PATH_IN) - $PAD - 240))
  ((BOTTOM=$(identify -format &apos;%h&apos; $PATH_IN) - $PAD))

  STRING=&quot;$(exifshort $PATH_IN)&quot;
  echo -e &quot;\nBurning exif data to image&quot;
  convert -pointsize $FONT_SIZE -fill yellow -draw &quot;text 10,$BOTTOM &apos;$STRING&apos;&quot; $PATH_IN $PATH_OUT
  echo -e &quot;\nBurning watermark to image&quot;
  convert -pointsize $FONT_SIZE -fill yellow -draw &quot;text $RIGHT,$BOTTOM &apos;karnsonline.com&apos;&quot; $PATH_OUT $PATH_OUT
}
</code></pre>
<!--kg-card-end: markdown--><p>Running the scripts</p><p>To show the short version of a photos metadata you can run the following command:</p><!--kg-card-begin: markdown--><pre><code class="language-shell">$ exifshort path/to/image/file.jpg
</code></pre>
<!--kg-card-end: markdown--><p>To burn the short version of the photos metadata to the image, run the following command:</p><!--kg-card-begin: markdown--><pre><code>burnexif path/to/image/file.jpg
</code></pre>
<!--kg-card-end: markdown--><p>The result will be a new image sitting right next to your source image with the addition of <code>-processed</code> to the file name. This script WILL NOT modify the original image source.</p>]]></content:encoded></item><item><title><![CDATA[Strawberry Super Moon]]></title><description><![CDATA[<p>Best shot I could get of the strawberry super moon with a foreground object. The humidity was definitely a factor in the focus here.</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2022/06/strawberry_super_moon-processed-2.jpg" class="kg-image" alt loading="lazy" width="2000" height="2997" srcset="https://karnsonline.com/content/images/size/w600/2022/06/strawberry_super_moon-processed-2.jpg 600w, https://karnsonline.com/content/images/size/w1000/2022/06/strawberry_super_moon-processed-2.jpg 1000w, https://karnsonline.com/content/images/size/w1600/2022/06/strawberry_super_moon-processed-2.jpg 1600w, https://karnsonline.com/content/images/size/w2400/2022/06/strawberry_super_moon-processed-2.jpg 2400w" sizes="(min-width: 720px) 720px"></figure>]]></description><link>https://karnsonline.com/strawberry-super-moon/</link><guid isPermaLink="false">66393ede5fb63a0001e86a6c</guid><category><![CDATA[astrophotography]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Wed, 15 Jun 2022 15:09:33 GMT</pubDate><content:encoded><![CDATA[<p>Best shot I could get of the strawberry super moon with a foreground object. The humidity was definitely a factor in the focus here.</p><figure class="kg-card kg-image-card"><img src="https://karnsonline.com/content/images/2022/06/strawberry_super_moon-processed-2.jpg" class="kg-image" alt loading="lazy" width="2000" height="2997" srcset="https://karnsonline.com/content/images/size/w600/2022/06/strawberry_super_moon-processed-2.jpg 600w, https://karnsonline.com/content/images/size/w1000/2022/06/strawberry_super_moon-processed-2.jpg 1000w, https://karnsonline.com/content/images/size/w1600/2022/06/strawberry_super_moon-processed-2.jpg 1600w, https://karnsonline.com/content/images/size/w2400/2022/06/strawberry_super_moon-processed-2.jpg 2400w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[2022-05-18]]></title><description><![CDATA[<figure class="kg-card kg-embed-card"><iframe style="border-radius: 12px" width="100%" height="380" title="Spotify Embed: 2022-05-18" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" src="https://open.spotify.com/embed/playlist/4j9QZxKLhkX57iI51v5gS1?utm_source=oembed"></iframe></figure>]]></description><link>https://karnsonline.com/2022-05-18/</link><guid isPermaLink="false">66393ede5fb63a0001e86a6b</guid><category><![CDATA[periodic-rotator]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Wed, 18 May 2022 18:09:42 GMT</pubDate><media:content url="https://karnsonline.com/content/images/2022/05/spotify-archive-HERO-5.png" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-embed-card"><iframe style="border-radius: 12px" width="100%" height="380" title="Spotify Embed: 2022-05-18" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" src="https://open.spotify.com/embed/playlist/4j9QZxKLhkX57iI51v5gS1?utm_source=oembed"></iframe></figure>]]></content:encoded></item><item><title><![CDATA[Shoot the Moon]]></title><description><![CDATA[<p>Unfortunately, it was raining for the lunar eclipse where I live so I got out a couple days before, and a day after to get some photos of the moon.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://karnsonline.com/content/images/2022/05/IMG_4967-2.JPG" class="kg-image" alt loading="lazy" width="2000" height="1333" srcset="https://karnsonline.com/content/images/size/w600/2022/05/IMG_4967-2.JPG 600w, https://karnsonline.com/content/images/size/w1000/2022/05/IMG_4967-2.JPG 1000w, https://karnsonline.com/content/images/size/w1600/2022/05/IMG_4967-2.JPG 1600w, https://karnsonline.com/content/images/size/w2400/2022/05/IMG_4967-2.JPG 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Canon EOS 80D + 150-600mm F5-6.3 DG OS HSM | Contemporary 015 @ 600.0 mm, ISO 800, 1/800 seconds, f/</figcaption></figure>]]></description><link>https://karnsonline.com/shoot-the-moon/</link><guid isPermaLink="false">66393ede5fb63a0001e86a65</guid><category><![CDATA[astrophotography]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Tue, 17 May 2022 15:39:06 GMT</pubDate><content:encoded><![CDATA[<p>Unfortunately, it was raining for the lunar eclipse where I live so I got out a couple days before, and a day after to get some photos of the moon.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://karnsonline.com/content/images/2022/05/IMG_4967-2.JPG" class="kg-image" alt loading="lazy" width="2000" height="1333" srcset="https://karnsonline.com/content/images/size/w600/2022/05/IMG_4967-2.JPG 600w, https://karnsonline.com/content/images/size/w1000/2022/05/IMG_4967-2.JPG 1000w, https://karnsonline.com/content/images/size/w1600/2022/05/IMG_4967-2.JPG 1600w, https://karnsonline.com/content/images/size/w2400/2022/05/IMG_4967-2.JPG 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Canon EOS 80D + 150-600mm F5-6.3 DG OS HSM | Contemporary 015 @ 600.0 mm, ISO 800, 1/800 seconds, f/6.4, 2022:05:12 20:45:50</figcaption></figure><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://karnsonline.com/content/images/2022/05/IMG_5001-4.jpg" class="kg-image" alt loading="lazy" width="2000" height="1335" srcset="https://karnsonline.com/content/images/size/w600/2022/05/IMG_5001-4.jpg 600w, https://karnsonline.com/content/images/size/w1000/2022/05/IMG_5001-4.jpg 1000w, https://karnsonline.com/content/images/size/w1600/2022/05/IMG_5001-4.jpg 1600w, https://karnsonline.com/content/images/size/w2400/2022/05/IMG_5001-4.jpg 2400w" sizes="(min-width: 1200px) 1200px"><figcaption>Canon EOS 80D + 150-600mm F5-6.3 DG OS HSM | Contemporary 015 @ 600.0 mm, ISO 100, 1/250 seconds, f/6.4, 2022:05:16 23:59:09</figcaption></figure>]]></content:encoded></item><item><title><![CDATA[Netcat Tar Pipe]]></title><description><![CDATA[<p>Lets face it, sometimes we need to move massive amounts of data between servers. wouldn&apos;t it be great if it wasn&apos;t so darn slow? In some cases <code>rsync</code> would do the job just fine, but it gets slowed down when it has to do checksum checks</p>]]></description><link>https://karnsonline.com/netcat-tar-pipe/</link><guid isPermaLink="false">66393ede5fb63a0001e86a64</guid><category><![CDATA[coding]]></category><category><![CDATA[rsync]]></category><category><![CDATA[ubuntu]]></category><category><![CDATA[linux]]></category><category><![CDATA[synology]]></category><category><![CDATA[netcat]]></category><category><![CDATA[tar]]></category><category><![CDATA[pipe]]></category><dc:creator><![CDATA[Deac Karns]]></dc:creator><pubDate>Tue, 12 Apr 2022 17:59:12 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1488229297570-58520851e868?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fGZpbGUlMjB0cmFuc2ZlcnxlbnwwfHx8fDE2NDk3ODUwOTk&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1488229297570-58520851e868?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fGZpbGUlMjB0cmFuc2ZlcnxlbnwwfHx8fDE2NDk3ODUwOTk&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Netcat Tar Pipe"><p>Lets face it, sometimes we need to move massive amounts of data between servers. wouldn&apos;t it be great if it wasn&apos;t so darn slow? In some cases <code>rsync</code> would do the job just fine, but it gets slowed down when it has to do checksum checks before and after a file transfer. Sure you could turn off the checksum checks but you would still be limited by rsync.</p><p>Enter <code>netcat tar pipe</code></p><p>we can use a combination of <code>netcat</code>, <code>tar</code>, and a <code>pipe</code> to blast data from one server to the other.</p><p>While copying files from an old NAS to a new NAS I was seeing the following transfer speeds.</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th style="text-align:center">Method</th>
<th style="text-align:center">Transfer Rate</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">rsync</td>
<td style="text-align:center">5mb/s</td>
</tr>
<tr>
<td style="text-align:center">netcat tar pipe</td>
<td style="text-align:center">71mb/s</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><h1 id="how-to-run-it">How to Run it</h1><h3 id="receiver">Receiver</h3><p>On the receiving machine start a listener in the directory where files will be received.</p><!--kg-card-begin: markdown--><pre><code>cd /path/to/destination/directory
ncat -l -p 7000 | tar -xpf -
</code></pre>
<!--kg-card-end: markdown--><h3 id="sender">Sender</h3><p>On the sending machine start a transfer to the listening receiver.</p><!--kg-card-begin: markdown--><pre><code>cd /path/to/source/directory
tar -cf - * | ncat &lt;hostname_of_receiver&gt; 7000
</code></pre>
<!--kg-card-end: markdown--><h2 id="synology">Synology</h2><p>Synology NAS&apos;s do not have <code>netcat</code> installed by default and you will need to install the <code>DiagnosisTool</code> to get access to the binary. Run the following command on your synology machine to install <code>netcat</code>.</p><!--kg-card-begin: markdown--><pre><code>sudo synogear install
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>