<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://macroscopicentric.net/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Macroscopicentric</title>
    <link>https://macroscopicentric.net/</link>
    <atom:link href="https://macroscopicentric.net/feed.xml" rel="self" type="application/rss+xml" />
    <description>This is a tech blog on the internet.</description>
    <language>en</language>
    <item>
      <title>Migrating from Jekyll to Eleventy</title>
      <link>https://macroscopicentric.net/blog/migrating-to-eleventy/</link>
      <description>&lt;h2&gt;TL;DR: Just the Migration Steps&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;add package.json and eleventy.config.cjs (see above)&lt;/li&gt;
&lt;li&gt;point layouts to &lt;code&gt;_layouts&lt;/code&gt; in eleventy.config.cjs&lt;/li&gt;
&lt;li&gt;convert &lt;code&gt;_config.yml&lt;/code&gt; to &lt;code&gt;_data/site.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;delete config.rb&lt;/li&gt;
&lt;li&gt;add .eleventyignore to ignore this readme&lt;/li&gt;
&lt;li&gt;replace my &lt;code&gt;jekyll-feed&lt;/code&gt; RSS plugin with eleventy&#39;s &lt;a href=&quot;https://www.11ty.dev/docs/plugins/rss/&quot;&gt;&lt;code&gt;rss&lt;/code&gt;&lt;/a&gt; plugin&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;_posts.json&lt;/code&gt; and a permalink to the about page&lt;/li&gt;
&lt;li&gt;delete a bunch of js and sass install eleventy&#39;s syntax highlighting plugin and update my code blocks&lt;/li&gt;
&lt;li&gt;for eleventy 3: update the page links for the index + pagination&lt;/li&gt;
&lt;li&gt;add a GH workflow, .nojekyll file, update repo settings in GH&lt;/li&gt;
&lt;li&gt;verify domain through GH user settings&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The Longer Version&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;For context: I started this process in January 2024 and finished in June 2025, hurrah personal projects, so there are references to Eleventy 2.0 below from before I migrated to 3.0.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I don&#39;t think there&#39;s a super clean config migration path from Jekyll to Eleventy but I might&#39;ve also been underusing Jekyll&#39;s config. Per &lt;a href=&quot;https://alex.pearwin.com/2020/06/jekyll-to-eleventy/&quot;&gt;this blog post&lt;/a&gt; I moved my &lt;code&gt;_config.yml&lt;/code&gt; (site-wide config) to &lt;code&gt;_data/site.json&lt;/code&gt;, and then had to decide what to do about build config, which I didn&#39;t really have an equivalent for in Jekyll (I did have a config.rb, but it was minimal and I just deleted it). Eleventy currently (as of January 2024) &lt;a href=&quot;https://www.11ty.dev/docs/config/&quot;&gt;has three config filename options&lt;/a&gt; for build config. I tried using &lt;code&gt;eleventy.config.js&lt;/code&gt; and specifying &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt; in my package.json settings per the recommendation of a friend, but that caused Eleventy to fatal. &lt;a href=&quot;https://www.11ty.dev/blog/canary-eleventy-v3/#new-features-and-a-short-upgrade-guide&quot;&gt;It looks like Eleventy is trying to migrate away from CJS&lt;/a&gt; but that work isn&#39;t yet complete, so I was able to leave the module type but did have to change to a &lt;code&gt;.cjs&lt;/code&gt; extension for the config file.&lt;/p&gt;
&lt;p&gt;Layouts are called layouts in 11ty&#39;s config and Jekyll&#39;s default pathing, but 11ty&#39;s path for them points to &lt;code&gt;_includes/&lt;/code&gt; by default, which honestly seems kind of weird to me as a design choice. I&#39;ve configured it in the general config file to just point to &lt;code&gt;_layouts/&lt;/code&gt; as it did in Jekyll.&lt;/p&gt;
&lt;p&gt;I also, for some reason I don&#39;t remember, had separate &lt;code&gt;_layouts&lt;/code&gt; AND &lt;code&gt;_includes&lt;/code&gt; directories, and my html page fragments (head, header, footer) were in &lt;code&gt;_includes&lt;/code&gt;, which made this especially confounding. It&#39;s at this point that I started enthusiastically copying from Alex Pearce&#39;s &lt;a href=&quot;https://github.com/alexpearce/home&quot;&gt;blog code&lt;/a&gt; and I realized the syntax within the Liquid templating was different so I copied his and it just worked.&lt;/p&gt;
&lt;p&gt;I then got stuck on my included scripts, which are probably absolute garbage and definitely include a fair amount of jquery (a combo of what&#39;s included by default by Jekyll and the theme I&#39;d picked) but while commenting them out did finally make the blog serve locally, it also changed the location of my header text as well as the font used for the header and headings. (No posts appear yet.) So at this point I want to make this just work with my existing jquery for the theme and then update this later.&lt;/p&gt;
&lt;p&gt;There&#39;s also some pathing wonkiness happening. Eleventy is turning my pathing for posts (which was &amp;quot;/blog/{page slug}/&amp;quot;) into &amp;quot;/blog/{page slug}/index.html&amp;quot;, which I think was my fault for the trailing slash, as Eleventy seems to turn those into directories. Removing the trailing slash makes the files end up in &lt;code&gt;_site&lt;/code&gt; in the expected location, although they now have no file extension and I&#39;m not sure if that&#39;s what Eleventy expects (even though they&#39;re properly formatted HTML). Similarly, my about page was going to &amp;quot;/about/index.html&amp;quot;. Deleting that file/directory and adding a permalink to about.md&#39;s front matter does fix the pathing, but now Eleventy can&#39;t seem to find the top-level (also without a file extension) about page. This is fixed now and then there were also some surprising things about front matter namespacing. I gained a lot by simply copying from &lt;a href=&quot;https://github.com/alexpearce/home/tree/eb2dfb5d20d5f1d59c278e57de453280f74aa252&quot;&gt;Alex Pearwin&#39;s code&lt;/a&gt; for &lt;em&gt;his&lt;/em&gt; Eleventy blog. My original (Jekyll&#39;s original?) pathing choices were even wackier, though, as my blog home &lt;em&gt;is&lt;/em&gt; my index.html but then every next page of blog posts is at &amp;quot;/blog/page{number}&amp;quot;, so I had to make a pretty goofy conditional to ensure the permalinks.&lt;/p&gt;
&lt;p&gt;I don&#39;t think I fully understand Eleventy&#39;s assumed pathing because making an html file called &amp;quot;about&amp;quot; at the top level meant Eleventy couldn&#39;t find it. But making the permalink &amp;quot;about.html&amp;quot; but linking to it everywhere else in the templates as &amp;quot;/about&amp;quot; seems to work just fine (the URL is just &amp;quot;/about&amp;quot;).&lt;/p&gt;
&lt;p&gt;There was also definitely something wonky happening with Sass, which worked out of the box with Jekyll, but in this way where I have no idea what Ruby libraries it was using and I think I deleted all my Ruby config, so I needed to go look those up. I&#39;ve installed the npm versions of Compass and Normalize but something had troubles finding Compass anyway. This is probably worth just blowing away and redoing from scratch since I have the final CSS I currently care about anyway. Also, I&#39;m terrible at SASS. I was able to just delete Compass altogether and move to a NPM package for vanilla Normalize CSS, but Susy will need to get converted into native CSS as well.&lt;/p&gt;
&lt;p&gt;A later update the above: this definitely isn&#39;t everything but Compass was Ruby code that is totally unsupported and no longer works with modern Ruby so I&#39;ve excised that entirely, but my understanding of CSS and SASS isn&#39;t good enough to figure out where it was being used and how extensively. So I&#39;ve just started with deleting the import. &lt;a href=&quot;https://jkc.codes/blog/using-sass-with-eleventy/&quot;&gt;This blog post&lt;/a&gt; for using Sass with Eleventy was extremely helpful for setting everything up in the interim.&lt;/p&gt;
&lt;p&gt;The last major thing was that I think either the entire template engine for Markdown or some of its config is different than what Jekyll used, because posts look mostly fine except for code blocks. The docs were pretty useful on this once I realized &lt;a href=&quot;https://www.11ty.dev/docs/plugins/syntaxhighlight/&quot;&gt;it&#39;s a plugin&lt;/a&gt;, but I got there via &lt;a href=&quot;https://nicolashery.com/moving-a-blog-from-jekyll-to-eleventy/#syntax-highlighting&quot;&gt;yet another blog post&lt;/a&gt;, and then I had to go to the Prism docs to figure out file pathing off of one of the CDNs for the theme I wanted.&lt;/p&gt;
&lt;p&gt;Interestingly, although I did a lot of work earlier to maintain my pathing from Jekyll, upgrading to Eleventy 3 actually caused build errors because I have so many pages that don&#39;t have extensions, which Eleventy really doesn&#39;t seem to like but (IIRC, because I don&#39;t think I would&#39;ve changed it) was a default in Jekyll. I&#39;ve compromised by removing the very silly conditional I mentioned above to try to maintain the pathing on the paginated blog pages after the index, but have exempted all posts via additional config in &lt;code&gt;_posts.json&lt;/code&gt; to try to keep the links consistent. I may regret this in the future, we&#39;ll see, but I&#39;d really like to not break the historical blog links.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Narrator&#39;s voice from 30 minutes into the future: She did regret this. (I solved it by going back to look at Alex Pearce&#39;s config for his posts, which has a trailing slash. I removed the exemption and added the trailing slash to my posts permalink config and now everything works great.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Finally, I had a bunch of issues deploying this via Github actions because I&#39;d been using Jekyll for so long that the entire pipeline was automagical to me. In general &lt;a href=&quot;https://www.11ty.dev/docs/deployment/&quot;&gt;the Eleventy deployment docs&lt;/a&gt; were extremely helpful and have specific config for your workflow since that&#39;s such a common use case. The one thing they didn&#39;t mention was that you also needed a &lt;code&gt;.nojekyll&lt;/code&gt; file at the top level of your repo if you were coming from Jekyll, but there are a plethora of blog posts mentioning this (ex: &lt;a href=&quot;https://www.linkedin.com/pulse/eleventy-github-pages-lea-tortay/&quot;&gt;Lea Tortay&#39;s blog post&lt;/a&gt;, which is commonly referenced, so that was easy to fix. I did miss an incredibly important step the first time, which was updating my repo settings to deploy from the gh-pages branch and not main. I also did not use &lt;code&gt;--pathprefix&lt;/code&gt;, which is included in a lot of the guides, because I deploy this at the top level of my GH pages. I do recommend adding &lt;code&gt;workflow_dispatch&lt;/code&gt; into your GH workflow triggers so you can retry it from the GH actions UI. Ex:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; main
  &lt;span class=&quot;token key atrule&quot;&gt;workflow_dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then had an incredibly confusing DNS issue, where I could see the blog at macroscopicentric.github.io but my own domain (macroscopicentric.net) gave me a Github Pages 404 instead. I&#39;m truly not sure what actually caused this to go away, because I already had CNAME config set up in my GH workflow and that didn&#39;t seem to be working (where the same CNAME had worked with Jekyll). But I did two things: I verified the domain through my user settings on Github and added the domain to the repo&#39;s GH Pages settings, and then I deleted the domain from the repo&#39;s GH Pages settings and re-ran my action, which recreated it. I&#39;m assuming it was the domain verification that solved my problem, but it also feels possible that there was some sort of bizarro caching problem at the DNS level from GH because my blog has been around so long with an unchanged CNAME. If anyone has a better idea of what might&#39;ve happened here, I&#39;d love to hear it!&lt;/p&gt;
</description>
      <pubDate>Sun, 08 Jun 2025 18:36:00 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/migrating-to-eleventy/</guid>
    </item>
    <item>
      <title>Zsh Prompt Editing</title>
      <link>https://macroscopicentric.net/blog/zsh-prompt-config/</link>
      <description>&lt;p&gt;I finally switched my default shell on my laptop (Mac) from bash to zsh. I&#39;d never bothered tinkering with a more sophisticated shell before this, so it was interesting to figure out what zsh could do. But I was frustrated because I had a nice prompt in bash, and it took me a while to recreate it.&lt;/p&gt;
&lt;p&gt;My bash prompt was pretty simple, it included my current directory, then my git branch, then status indicators for different types of dirty state in a git repo (specifically, staged vs. unstaged changes). It also used to have a unicode crown emoji, but after working with bash on a lot of hosts with older versions of bash that didn&#39;t do well with unicode, I&#39;d pulled the crown out years ago. (I was hopeful that I could add it back in, at least for my personal computer!)&lt;/p&gt;
&lt;p&gt;(Sidenote: I looked into oh-my-zsh and then decided it was too complicated as a framework for my needs, so I&#39;ll be ignoring it here.)&lt;/p&gt;
&lt;p&gt;Replicating my current directory with color-coding was very easy in zsh. It was actually even easier than in bash, since zsh accepts some strings for colors rather than codepoints. After reading &lt;a href=&quot;https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html#Prompt-Expansion&quot;&gt;the zsh prompt expansion docs&lt;/a&gt; and &lt;a href=&quot;https://scriptingosx.com/2019/07/moving-to-zsh-06-customizing-the-zsh-prompt/&quot;&gt;this 2019 blog post about customizing your zsh prompt&lt;/a&gt;, I ended up with:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;PROMPT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;%B%F{magenta}%1/%f%b 👑 &quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here I initiate bolded and magenta-colored text (&lt;code&gt;%B%F{magenta}&lt;/code&gt;), then print one directory out of my working directory, using an absolute path regardless of whether I&#39;m inside my home directory (&lt;code&gt;%1/&lt;/code&gt;), then undo the magenta color and bolding (&lt;code&gt;%f%b&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Next I wanted to replicate the git-related part of my bash prompt. Here zsh is, again, more sophisticated than bash, and has a bunch of basic out-of-the-box git functionality. If you just want to display your branch name and/or dirty state, zsh can do it right out of the box. I found &lt;a href=&quot;https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh&quot;&gt;git&#39;s own documentation of how to display git info in the zsh prompt&lt;/a&gt; super helpful, and it also linked directly to &lt;a href=&quot;https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#Version-Control-Information&quot;&gt;another section of the zsh docs on zsh and version control systems&lt;/a&gt;. After some trial and error (and more help from other people&#39;s blog posts), I had this:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# grab current branch and display in prompt&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# source: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh&lt;/span&gt;
autoload &lt;span class=&quot;token parameter variable&quot;&gt;-Uz&lt;/span&gt; vcs_info add-zsh-hook
&lt;span class=&quot;token function-name function&quot;&gt;precmd_vcs_info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; vcs_info &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;precmd_functions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; precmd_vcs_info &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
setopt prompt_subst

&lt;span class=&quot;token comment&quot;&gt;# These lines are specifically for staged + unstaged changes&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# source: https://salferrarello.com/zsh-git-status-prompt/&lt;/span&gt;
add-zsh-hook precmd vcs_info
zstyle &lt;span class=&quot;token string&quot;&gt;&#39;:vcs_info:*&#39;&lt;/span&gt; check-for-changes &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
zstyle &lt;span class=&quot;token string&quot;&gt;&#39;:vcs_info:*&#39;&lt;/span&gt; unstagedstr &lt;span class=&quot;token string&quot;&gt;&#39; *&#39;&lt;/span&gt;
zstyle &lt;span class=&quot;token string&quot;&gt;&#39;:vcs_info:*&#39;&lt;/span&gt; stagedstr &lt;span class=&quot;token string&quot;&gt;&#39; +&#39;&lt;/span&gt;

zstyle &lt;span class=&quot;token string&quot;&gt;&#39;:vcs_info:git:*&#39;&lt;/span&gt; formats &lt;span class=&quot;token string&quot;&gt;&#39;(%b%u%c)&#39;&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;PROMPT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;%B%F{magenta}%1/%f%b ${vcs_info_msg_0_} 👑 &#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This did everything described above (show the git branch and all dirty states using different symbols), which was almost what I wanted. But I also really wanted part or all of the git part of my prompt to be color-coded red if there was &lt;em&gt;any&lt;/em&gt; type of dirty state. After some spelunking through the git and zsh documentation, I decided that &lt;code&gt;vcs_info&lt;/code&gt; was neat but just didn&#39;t have enough power to allow me to conditionally format the magic &lt;code&gt;vcs_info_msg_0&lt;/code&gt; variable. So I switched tactics, and went back to an old and reliable standby: &lt;a href=&quot;https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh&quot;&gt;the &lt;code&gt;git-prompt.sh&lt;/code&gt; script in the git repo itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;d used this script before, to do the same things in bash, but I hadn&#39;t yet installed or used it with zsh. So I explicitly included that in my .zshrc:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; ~/.git-prompt.sh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then I did something I&#39;ve honestly never done before, and I went and read that script&#39;s whole dang docstring to figure out if there was an easy way to do what I wanted. And there was! Here&#39;s the final draft of my prompt, which felt very simple in the end:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; ~/.git-prompt.sh

&lt;span class=&quot;token comment&quot;&gt;# allow prompt substitution, show dirty state in color (incl. untracked files), define prompt&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# source: the git-prompt.sh (above) docstring&lt;/span&gt;
setopt prompt_subst
&lt;span class=&quot;token assign-left variable&quot;&gt;GIT_PS1_SHOWDIRTYSTATE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;GIT_PS1_SHOWCOLORHINTS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;GIT_PS1_SHOWUNTRACKEDFILES&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token function-name function&quot;&gt;precmd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; __git_ps1 &lt;span class=&quot;token string&quot;&gt;&quot;%B%F{magenta}%1/%f%b &quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;👑 &quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;| %s &quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Second sidenote: I did switch from assigning to &lt;code&gt;PROMPT&lt;/code&gt; to using &lt;code&gt;precmd ()&lt;/code&gt; here because the git-prompt.sh docstring recommended it as faster, but I&#39;m not convinced it&#39;s faster for me. I haven&#39;t looked into whether this is user error, or zsh being different, or something else I haven&#39;t thought of.)&lt;/p&gt;
</description>
      <pubDate>Tue, 14 Mar 2023 17:53:00 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/zsh-prompt-config/</guid>
    </item>
    <item>
      <title>An Introduction to Command-Line Unix Tools</title>
      <link>https://macroscopicentric.net/blog/unix-tools/</link>
      <description>&lt;p&gt;I&#39;m relatively new to Unix tools, and when I began, I was frustrated because I felt like the only way I knew how to find new tools was to ask people with more experience. The goal of this post is to provide some starting places if you&#39;d like to learn more about what you can do on the command line, but it&#39;s not intended to be an exhaustive list.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;apropos&lt;/code&gt; - I&#39;m listing this one first because hopefully it will help you find others! Searches your man pages for the keyword(s) you pass into it. Ex: &lt;code&gt;apropos networking&lt;/code&gt; will search for man pages that include the word &amp;quot;networking.&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;curl&lt;/code&gt; - get data over a network, via basically any protocol you can think of. It has a LOT of flags and can do oodles of stuff. I once made a joke about how I&#39;d be back in six hours after hunting through the curl docs to find the flag I needed. The joke was on me; it really did take me that long to read the entire man page. Ex: &lt;code&gt;curl http://www.example.com -v&lt;/code&gt; will give you the HTTP response (including headers) for a GET to www.example.com. Alternative (Linux only): &lt;code&gt;wget&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;netstat&lt;/code&gt; - show network connections. Ex: &lt;a href=&quot;https://writing.natwelch.com/post/581&quot;&gt;&lt;code&gt;netstat -tunapl&lt;/code&gt;&lt;/a&gt; (example is Linux only).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ps&lt;/code&gt; - list currently-running processes. Ex: &lt;code&gt;ps aux&lt;/code&gt; will list all processes for all users, including the percentages of CPU and memory being used. Alternative: &lt;code&gt;pstree&lt;/code&gt; is a Linux-only tool that will show you a graph of all parent/children process relationships.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;top&lt;/code&gt; - live view of current processes, including things like CPU percentage.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strace&lt;/code&gt; (Linux only) - trace system calls. Alternative for Mac OSX: &lt;a href=&quot;https://8thlight.com/blog/colin-jones/2015/11/06/dtrace-even-better-than-strace-for-osx.html&quot;&gt;&lt;code&gt;dtrace&lt;/code&gt;&lt;/a&gt;. I&#39;m not going to explain this one too much because &lt;a href=&quot;http://jvns.ca/&quot;&gt;Julia Evans&lt;/a&gt; wrote &lt;a href=&quot;http://jvns.ca/strace-zine-unfolded.pdf&quot;&gt;a great zine on it&lt;/a&gt;. If you&#39;re not sure what system calls are, Julia&#39;s zine explains that too!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/proc&lt;/code&gt; (Linux only) - a virtual directory that keeps track of information related to currently running processes. Once you have a process&#39;s PID, you can go to &lt;code&gt;/proc/&amp;lt;PID&amp;gt;&lt;/code&gt; to find a variety of info. Ex: &lt;code&gt;/proc/&amp;lt;PID&amp;gt;/fd&lt;/code&gt; is a directory listing all of the file descriptors (files being touched) for the given process, and &lt;code&gt;/proc/&amp;lt;PID&amp;gt;/environ&lt;/code&gt; is a file listing a process&#39;s environment.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Further Reading&lt;/h4&gt;
&lt;p&gt;The &lt;a href=&quot;http://tldr-pages.github.io/&quot;&gt;TLDR Pages&lt;/a&gt; project has simplified explanations of the content of some man pages.&lt;/p&gt;
&lt;p&gt;If you&#39;re looking for something more exhaustive, the &lt;a href=&quot;https://www.kernel.org/doc/man-pages/&quot;&gt;Linux man-pages project&lt;/a&gt; might help.&lt;/p&gt;
&lt;p&gt;Netflix has a great post on &lt;a href=&quot;http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html&quot;&gt;&amp;quot;Linux Performance Analysis in 60 Seconds&amp;quot;&lt;/a&gt; with a list of Unix tools useful for troubleshooting performance issues.&lt;/p&gt;
</description>
      <pubDate>Thu, 01 Sep 2016 22:23:48 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/unix-tools/</guid>
    </item>
    <item>
      <title>Using Other People&#39;s Code</title>
      <link>https://macroscopicentric.net/blog/other-peoples-code/</link>
      <description>&lt;p&gt;Including other people&#39;s code in your program means you don&#39;t have to write everything from scratch. You don&#39;t have to solve every problem on your own, and it&#39;s often faster and more efficient to use something off the shelf. There are three ways to include other people&#39;s code in what you&#39;re doing.&lt;/p&gt;
&lt;p&gt;The first is something you already do: using the core of a programming language. If you&#39;re using Python, for example, every time you use &lt;code&gt;import&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, or &lt;code&gt;return&lt;/code&gt;, you&#39;re using code other people have written. These specific examples are called keywords, and you can easily find a list of &lt;a href=&quot;http://www.programiz.com/python-programming/keyword-list&quot;&gt;all Python keywords&lt;/a&gt; online. Other examples of things in Python&#39;s core include its basic data types, such as strings, lists, and dictionaries, and all the methods you can use on those types.&lt;/p&gt;
&lt;p&gt;In addition to a language&#39;s core, however, there&#39;s also the language&#39;s standard library. A standard library is a collection of modules that come prepackaged with your language. When the programming language was installed on your computer, everything in the standard library was installed with it. The standard library comes ready to use. All you have to do is include the module you want to use at the top of your file. In Python, one module in the standard library that often comes in handy is the &lt;code&gt;collections&lt;/code&gt; module. Once you import the &lt;code&gt;collections&lt;/code&gt; module, you can use any data type from within it, such as its &lt;code&gt;OrderedDict&lt;/code&gt; and &lt;code&gt;defaultdict&lt;/code&gt;. (I highly recommend &lt;a href=&quot;https://pymotw.com/3/&quot;&gt;Python Module of the Week&lt;/a&gt; if you want to know more about what&#39;s part of Python&#39;s standard library.) So you could do something like:&lt;/p&gt;
&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; collections &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; defaultdict

example &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; defaultdict&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;marshmallow&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; example&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# &#39;marshmallow&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The third way to use people&#39;s code is to use external libraries. Perhaps you want to use use an external API, such as Twitter&#39;s API. One way you could interact with Twitter&#39;s API is by using Python&#39;s built-in module &lt;code&gt;urllib2&lt;/code&gt;, which is part of the standard library:&lt;/p&gt;
&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;	&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; urllib2

	response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urllib2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;urlopen&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;http://twitter.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# list of headers from &#39;GET http://twitter.com&#39;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# body of &#39;GET http://twitter.com&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can absolutely use Twitter&#39;s API (or any other public API) this way, but it&#39;s tedious! It will take a lot of code to authenticate you, then even more to fetch and parse whatever data you want access to, whether it&#39;s your own tweets, or tweets including a certain keyword, or someone else&#39;s mentions, etc. Wouldn&#39;t it be neat if someone else had done all the repetitive, boring work of making authentication work and automatically parsing the response? This is where third-party libraries come in; &lt;a href=&quot;https://dev.twitter.com/overview/api/twitter-libraries&quot;&gt;lots of people&lt;/a&gt; have already built external libraries that have abstracted out the repetitive parts of writing code to interact with the Twitter API. To use one, all you have to do is &lt;code&gt;pip install &amp;lt;library name&amp;gt;&lt;/code&gt; from your terminal, and then import it into your file. Voila, you can now use someone else&#39;s third-party library from your own program!&lt;/p&gt;
&lt;p&gt;There are some hazards to using other people&#39;s code. Sometimes you might have compatibility issues, or perhaps the library you want to use hasn&#39;t been updated in a really long time. Pay attention to the libraries you use. How thorough is the README? Is there additional documentation? Do they look like they&#39;re being worked on regularly? Do they have an IRC channel where you can ask questions if you&#39;d like?&lt;/p&gt;
&lt;p&gt;Using third-party libraries can mean trading convenience for behind-the-scenes complexity, and it may not always be worth it. If you&#39;re doing something simple, it might be better to use something from your language&#39;s standard library. But it&#39;s always good to know what other options exist.&lt;/p&gt;
</description>
      <pubDate>Mon, 25 Jan 2016 22:08:00 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/other-peoples-code/</guid>
    </item>
    <item>
      <title>Educational Resources for Beginners in Python</title>
      <link>https://macroscopicentric.net/blog/resources-for-beginners/</link>
      <description>&lt;p&gt;This list is mostly Python-specific since that&#39;s how I learned to program, but some of these resources are language-agnostic. Feel free to try some out and then drop them if they don&#39;t work for you! The important thing is that you&#39;re learning, so find a learning tool that fits your style and needs.&lt;/p&gt;
&lt;h2&gt;Websites&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://teamtreehouse.com/&quot;&gt;Treehouse&lt;/a&gt; and &lt;a href=&quot;http://www.lynda.com/default.aspx&quot;&gt;Lynda&lt;/a&gt; are both subscription websites that have tons of educational videos and practice material for you to follow along. I&#39;ve never used Lynda for this purpose, but Treehouse is beginner-friendly and covers a lot of topics, has forums to ask questions if you get stuck, and has workspaces where you can write and run code on the website instead of needing to store it on your computer. Treehouse also has &lt;a href=&quot;http://blog.teamtreehouse.com/&quot;&gt;a blog&lt;/a&gt; you can see without having an account and might have some helpful information.&lt;/p&gt;
&lt;p&gt;If you need free resources, MOOCs (Massive Open Online Courses) are your friend. Websites like &lt;a href=&quot;https://www.khanacademy.org/computing&quot;&gt;Khan Academy&lt;/a&gt;, &lt;a href=&quot;https://www.edx.org/course/subject/computer-science&quot;&gt;edX&lt;/a&gt;, and &lt;a href=&quot;https://www.coursera.org/browse/computer-science?languages=en&quot;&gt;Coursera&lt;/a&gt; have a bunch of educational videos that are organized into courses. Some courses have a syllabus, homework, and projects. Many have forums where you can ask questions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://learnpythonthehardway.org/&quot;&gt;Learn Python the Hard Way&lt;/a&gt; is a free online resource, although you can pay for a physical book or tutorial videos. Zed Shaw has a very opinionated teaching method, and tends to make you do things before explaining them. This works very well for some people, but not so well for others. (He also has a variety of other &lt;a href=&quot;http://learncodethehardway.org/&quot;&gt;Learn Code the Hard Way&lt;/a&gt; resources for learning Ruby, SQL, C, and regex.)&lt;/p&gt;
&lt;p&gt;If you&#39;re comfortable with the basics in Python and can write and use classes and short programs on your own, try going through &lt;a href=&quot;https://pymotw.com/3/&quot;&gt;Python Module of the Week&lt;/a&gt;. It&#39;s a website based on a set of blog posts where the author went through each module in Python&#39;s standard library. Each post has example usages for the module and its methods, and a lot of people find the organization very helpful.&lt;/p&gt;
&lt;h2&gt;Specific Tutorials/Walkthroughs&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming&quot;&gt;A Practical Introduction to Functional Programming&lt;/a&gt; by Mary Rose Cook. If you&#39;re not sure what functional programming is, check out that post and &lt;a href=&quot;https://www.quora.com/What-is-object-oriented-programming?share=1&quot;&gt;this Quora answer&lt;/a&gt;, and keep in mind that functional programming and object-oriented programming are not a dichotomy. You can use elements of both in the same program! Another of her blog posts, &lt;a href=&quot;http://maryrosecook.com/blog/post/my-speech-to-new-hacker-schoolers&quot;&gt;&amp;quot;My speech to new Recursers,&amp;quot;&lt;/a&gt; includes some great general advice (at the bottom) about what to focus on when learning how to program.&lt;/p&gt;
&lt;p&gt;She also has &lt;a href=&quot;http://maryrosecook.com/blog/post/git-in-six-hundred-words&quot;&gt;&amp;quot;Git in six hundred words&amp;quot;&lt;/a&gt; and an extensive essay called &lt;a href=&quot;http://maryrosecook.com/blog/post/git-from-the-inside-out&quot;&gt;&amp;quot;Git from the Inside Out,&amp;quot;&lt;/a&gt;. These are most helpful if you&#39;re already familiar with the most common git commands, such as &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git branch&lt;/code&gt;, etc, and want to know what git is doing under the hood when you type them. If you just want to figure out how to use git, you might find &lt;a href=&quot;https://www.atlassian.com/git/tutorials&quot;&gt;Atlassian&#39;s git tutorials&lt;/a&gt; useful instead.&lt;/p&gt;
&lt;p&gt;Relatedly, if you&#39;re confused by how git works, that&#39;s okay! &lt;a href=&quot;http://stevelosh.com/blog/2013/04/git-koans/&quot;&gt;Entire articles&lt;/a&gt; have been written on how unintuitive git&#39;s interface is. I highly recommend learning the basics of how to use git from the command line and how it works under the hood at some point. But if not knowing git means you&#39;re being blocked on writing new programs, feel free to use the desktop client in the meantime. The GitHub team has worked hard to make the desktop client easy to use, so use it if it helps!&lt;/p&gt;
&lt;p&gt;For Javascript, Julie Pagano wrote a really wonderful post titled &lt;a href=&quot;http://juliepagano.com/blog/2014/05/18/javascript-debugging-for-beginners/&quot;&gt;&amp;quot;Javascript Debugging for Beginners.&amp;quot;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you&#39;re ready to build something on your own, building a Twitter bot is usually a good start. There are a lot of resources that can help. Sumana Harihareswara&#39;s blog post &lt;a href=&quot;http://www.harihareswara.net/sumana/2013/12/5/0&quot;&gt;&amp;quot;Fisher-Price&#39;s My First Twitter Bot&amp;quot;&lt;/a&gt; is a great tutorial in Python. Disclaimer: Twitter bots are a fun and interesting project, but learn from my mistake: make your bot either opt-in (people follow it/tweet at it/etc) or non-interactive. Nobody likes a bot that spams people.&lt;/p&gt;
&lt;h2&gt;Finding a Mentor&lt;/h2&gt;
&lt;p&gt;It&#39;s tough to learn how to program without personalized help from a real person. Local meetups are a great way to meet both other beginners and people who can help you. Meetups specifically designed to help beginners are probably your best bet. &lt;a href=&quot;http://www.pyladies.com/&quot;&gt;Pyladies&lt;/a&gt; is an awesome group that focuses on supporting female Python programmers, has a bunch of &lt;a href=&quot;http://www.pyladies.com/locations/&quot;&gt;locations&lt;/a&gt;, and is incredibly beginner-friendly.&lt;/p&gt;
&lt;p&gt;I live in Portland (OR), and there&#39;s a group here called &lt;a href=&quot;http://www.meetup.com/Mentorship-Saturdays/&quot;&gt;Mentorship Saturdays&lt;/a&gt; that&#39;s open to everyone and aimed at beginners who need coding help or career advice. And although you can use Meetup to find local groups wherever you are, in Portland we also have &lt;a href=&quot;http://calagator.org/&quot;&gt;Calagator&lt;/a&gt;, an open source calendar specifically for tech events.&lt;/p&gt;
&lt;p&gt;Speaking of open source, if you&#39;re interested in contributing to an open source project (it&#39;s great experience!) but aren&#39;t sure how to start, &lt;a href=&quot;https://openhatch.org/&quot;&gt;Open Hatch&lt;/a&gt; is a great website that aims to connect beginners in open source to beginner-friendly open source projects. Open Hatch itself is open source and written in Python, so that&#39;s one project you could work on!&lt;/p&gt;
&lt;p&gt;Finally, the Recurse Center has just announced a new initiative called &lt;a href=&quot;https://www.recurse.com/blog/99-free-one-on-one-mentorship-for-new-programmers&quot;&gt;RC Start&lt;/a&gt;, where beginning programmers can sign up for a mentor and receive three 45 min one-on-one sessions (via Skype or in person). Go to the blog post for more info.&lt;/p&gt;
</description>
      <pubDate>Sun, 24 Jan 2016 11:13:00 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/resources-for-beginners/</guid>
    </item>
    <item>
      <title>Configuration Management for Beginners</title>
      <link>https://macroscopicentric.net/blog/config-management/</link>
      <description>&lt;h2&gt;Using Chef as an Example&lt;/h2&gt;
&lt;h3&gt;Who is this blog post meant for?&lt;/h3&gt;
&lt;p&gt;This post is aimed at software engineers who have used configuration management software (especially Chef) without necessarily being comfortable with the process or fully understanding what they were doing. I spend a lot of time working with Chef in my day job, and frequently explain what&#39;s happening behind the scenes to software engineers in other sections of the engineering org who rarely make Chef changes. This blog post is a distillation of how I normally explain what configuration changes they&#39;re making and why.&lt;/p&gt;
&lt;h3&gt;What is configuration management?&lt;/h3&gt;
&lt;p&gt;Configuration management is the process of creating and maintaining consistent state across a complex system. If you&#39;re curious, there&#39;s a more comprehensive definition and a long list of industries that use configuration management on &lt;a href=&quot;https://en.wikipedia.org/wiki/Configuration_management&quot;&gt;the Wikipedia page&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Why does configuration management software exist?&lt;/h3&gt;
&lt;p&gt;Say you have 1000 hosts that perform different functions. Some are web servers, some are mail servers, some host your database. You want some software on all of them: perhaps git, or monitoring software. And you want that software to be configured similarly on all of the hosts as well. For example, to ensure that the version of git is the same on every host, or that your LDAP configuration is the same everywhere.&lt;/p&gt;
&lt;p&gt;In addition, you want some software on just some of your hosts. Of course you&#39;d want a web server (Apache, Nginx, something else) installed on your web server hosts. You&#39;ll need a mail server for the mail server hosts, and a database on your database hosts. And again, you&#39;d want the configuration for all of &lt;em&gt;those&lt;/em&gt; pieces of software to also be consistent. Configuration management software allows you to manage all this configuration from one central location, rather than logging onto each individual host to set this up manually yourself. It allows you to start thinking of your hosts as a fleet and manage them as such.&lt;/p&gt;
&lt;h3&gt;So how does Chef do this?&lt;/h3&gt;
&lt;p&gt;A Chef repo has four major parts: data bags, recipes, roles, and environments.&lt;/p&gt;
&lt;h4&gt;Data Bags&lt;/h4&gt;
&lt;p&gt;Data bags are the simplest part; they&#39;re just files you can fill with whatever JSON you want to have access to on a host (typically called a node in Chef parlance). Data bags are organized into separate subdirectories depending on what type of data they contain. These organizational lines are entirely human-defined, so you can create whatever sort of subdirectory organization makes the most sense to you. Because data bags are so freeform, people put all sorts of things in them. &lt;a href=&quot;https://blog.dnsimple.com/2017/05/databag_refactor/&quot;&gt;Here&#39;s a great blog post&lt;/a&gt; by DNSimple where they use a data bag to store network config.&lt;/p&gt;
&lt;h4&gt;Recipes&lt;/h4&gt;
&lt;p&gt;A recipe is an individual script written in a Ruby DSL (&lt;a href=&quot;https://en.wikipedia.org/wiki/Domain-specific_language&quot;&gt;Domain-specific language&lt;/a&gt;). A recipe can include a variety of steps, such as installing a software package or installing a file from a template. Steps in a recipe are attempted in order. Because Chef recipes are just Ruby code with some syntactic sugar, you can include logic within your recipe to only perform certain actions if the node has certain attributes, such as if it has a specific version of your operating system. Additionally, you can create your own attributes and attach them to certain nodes to use like tags. You can also consult the information contained in data bags from recipes.&lt;/p&gt;
&lt;p&gt;Recipes are collected into cookbooks, which, like the data bags, are purely for human readability. However, cookbooks are generally organized along software lines. So for example, you might have a MySQL cookbook, where all the recipes contained within the cookbook relate to the installation and configuration of MySQL. You can also download &lt;em&gt;community cookbooks&lt;/em&gt;, cookbooks created by other people, on the &lt;a href=&quot;https://supermarket.chef.io/&quot;&gt;Supermarket&lt;/a&gt;. A cookbook should always have a &amp;quot;default&amp;quot; recipe. It may also have other recipes for installing the same piece of software but a different version, or be customized for a specific type of host, etc.&lt;/p&gt;
&lt;p&gt;Cookbooks are versioned within Chef. When you make changes to a recipe, you must bump the respective cookbook version and push the new cookbook version to the Chef server.&lt;/p&gt;
&lt;h4&gt;Roles&lt;/h4&gt;
&lt;p&gt;A role is a functional collection of recipes that are all needed to build a specific type of host. Roles can contain other roles, so you can choose to create a base role as you would a base image, and add that base role to every new role you create from then on. A role executes all roles and recipes listed within it in order, which can cause ordering problems as your system grows in complexity and more roles and recipes are added.&lt;/p&gt;
&lt;h4&gt;Environments&lt;/h4&gt;
&lt;p&gt;An environment file is essentially a long list of key/value pairs where the key is a cookbook name and the value is a version number. After editing a cookbook and bumping the cookbook&#39;s version number, you must update the corresponding version number in any relevant environment files. This tells Chef to actually start using the new cookbook version in all roles that include it.&lt;/p&gt;
&lt;p&gt;Why would you have different environment files? Environment files allow you to build different ecosystems, because you can have environment files with different cookbooks or even different versions of the same cookbook. For example, you might have different environment files for different deployment environments, such as one for staging and one for production. Or maybe you have one environment file that acts as staging for infrastructure changes themselves, and after making changes to a file in a cookbook you update the cookbook in your infrastructure staging environment file before rolling out the same cookbook version to your production systems.&lt;/p&gt;
&lt;h3&gt;Okay, but how do my changes actually take effect?&lt;/h3&gt;
&lt;p&gt;Chef has two functional parts. The Chef server stores all of your node and repo data. When you upload cookbook changes, for example, this is where those changes go. The other major part of Chef is chef-client, the daemon that sits on every node and regularly checks into the Chef server to see if there are any cookbook updates relevant to that node. For any updated cookbooks, chef-client will diff the changes between the old version and the new version, and then try to implement the diff. In other words, with Chef, you can make incremental updates to some or all hosts at the same time.&lt;/p&gt;
&lt;h3&gt;Some related concepts:&lt;/h3&gt;
&lt;h4&gt;What are some alternatives to Chef?&lt;/h4&gt;
&lt;p&gt;There are two other common alternatives to Chef: &lt;a href=&quot;http://www.puppet.com/&quot;&gt;Puppet&lt;/a&gt; and &lt;a href=&quot;https://www.ansible.com&quot;&gt;Ansible&lt;/a&gt;. You can find a full list of configuration management software &lt;a href=&quot;https://en.wikipedia.org/wiki/Comparison_of_open-source_configuration_management_software&quot;&gt;on Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Infrastructure as Code, or Configuration as Code&lt;/h4&gt;
&lt;p&gt;Exactly what it sounds like! The saving of your configuration, from the creation of your instances in the first place if you&#39;re in the cloud (how much memory do they have? how much disk space?) to the software installed on them (which image are you using for this host? what operating system? what software config?), as code in a repository rather than ephemeral values that you edit by hand. Config as code allows you to use version control software to manage it, giving you all the benefits that come with VCS, such as being able to roll back to older versions of the code and tracking who&#39;s made what changes to the code and why. &lt;a href=&quot;https://en.wikipedia.org/wiki/Infrastructure_as_code&quot;&gt;The Wikipedia page on Infrastructure as Code&lt;/a&gt; is great if you&#39;re looking for more info on this concept.&lt;/p&gt;
&lt;h4&gt;Mutable vs. Immutable Infrastructure&lt;/h4&gt;
&lt;p&gt;Mutable infrastructure describes a system where you can modify existing resources, such as Chef and other configuration management tools (see above). In Chef, you can make changes to already-existing hosts by adding new steps to existing recipes, or adding recipes altogether.&lt;/p&gt;
&lt;p&gt;In a system with immutable infrastructure, on the other hand, all changes involve destroying and fully recreating resources. Containers like Docker, and container orchestration systems like Kubernetes, are good examples of systems with immutable infrastructure.&lt;/p&gt;
&lt;p&gt;Which is better? It depends on what you&#39;re looking for. In a pure Chef system, creating new resources is costly because you create them from scratch every time, but every subsequent update is relatively cheap. In a pure immutable infrastructure system, the cost is in the creation of the image itself, so it depends on how frequently you make changes to the image, but creating new resources from that image is usually pretty cheap. A lot of places have arrived at a hybrid approach for this reason, where they have base images that are updated occasionally, and then have software that incrementally adds other software and configuration that&#39;s updated more frequently on top of what&#39;s being installed in the base image.&lt;/p&gt;
&lt;p&gt;Like many things in software engineering, the question of whether to use mutable or immutable infrastructure (or a hybrid) has no one right answer. It all depends on what you currently do, how costly it would be to change, and where you and your organization ultimately want to spend your engineering time and energy.&lt;/p&gt;
</description>
      <pubDate>Sat, 23 Jan 2016 16:17:00 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/config-management/</guid>
    </item>
    <item>
      <title>What is Object-Oriented Programming?</title>
      <link>https://macroscopicentric.net/blog/object-oriented/</link>
      <description>&lt;p&gt;Object-oriented programming is the idea that data has its own identity and methods so it can do things for itself, instead of a workflow where functions do things &lt;em&gt;to&lt;/em&gt; the data. The main goal here is delegation: you can tell an object what you want it to do, but you don&#39;t have to worry about the details of &lt;em&gt;how&lt;/em&gt; it will accomplish what you want. This allows you to decouple (remove unnecessary dependencies) your code. Decoupling your code means you can change the implementation of an object&#39;s method without needing to change the code calling that method, and vice versa. (If you found this explanation confusing, here&#39;s a &lt;a href=&quot;https://www.quora.com/What-is-object-oriented-programming?share=1&quot;&gt;Quora post&lt;/a&gt; that tries to answer the same question.)&lt;/p&gt;
&lt;p&gt;In practice, object-oriented programming works by creating classes that have variables and methods, then creating instances of that class that store different information in the variables but have similar ways of interacting with it through the methods. You can have a lot of instances of the same class, so a common metaphor is to explain a class as a rubber stamp, and instances of that class like the images created by the rubber stamp. I like to compare classes to the Platonic ideal.* A class is a Platonic ideal of an object, and instances are actual working examples of the class. Like the Platonic ideal of a thing, a class is something you don&#39;t usually interact with directly. Instead, you make and then interact with instances of it. So if we use the example of a horse (a common example when explaining the Platonic ideal), you&#39;d have a class Horse, and then individual horse instances of Horse that contain slightly different data, or ideas of what a horse can be. Perhaps your Horse class contains variables for things like age, gender, color or breed, height, etc. Then you could have different instances of Horse with different configurations, such as &amp;quot;a pinto mare&amp;quot; or &amp;quot;a bay yearling&amp;quot; or &amp;quot;a grey stallion.&amp;quot; All these individual horses are still instances of Horse, so they all know how to do things that all horses should be able to do, like run. Putting all this together, we could write an example class and instance like this:&lt;/p&gt;
&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;	&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Horse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; age&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gender&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; color&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
			self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; age
			self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;gender &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gender
			self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; color

		&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; distance&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The %s horse runs %d miles.&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;color&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; distance&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

	pinto_mare &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Horse&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;female&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;pinto&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	pinto_mare&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;run&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# &quot;The pinto horse runs 4 miles.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In a real program, you&#39;d probably have a lot more than just one Horse instance. All instances of Horse would know how to run, and possibly jump, and eat, and do other things. Then instead of needing to manually move the horse (which involves knowing a) how to move a horse and b) how to move &lt;em&gt;this specific&lt;/em&gt; horse), you&#39;d simply type &lt;code&gt;pinto_mare.run(4)&lt;/code&gt; or &lt;code&gt;pinto_mare.walk(1)&lt;/code&gt; and the horse would move itself.&lt;/p&gt;
&lt;p&gt;Not everything needs its own class though! How do you tell when something is large enough to warrant writing a class for it? One good marker is trying to pass around a cluster of data all together and/or doing repetitive things to it. These actions signal that you&#39;re thinking of that data as a unified entity, at which point it might be worthwhile creating a separate class for it.&lt;/p&gt;
&lt;p&gt;Writing object-oriented code allows you to decouple your code, which makes it more flexible, since you can change something without needing to also change everything that uses it. This makes both testing and editing your code much easier and less error-prone. I mean, who &lt;em&gt;doesn&#39;t&lt;/em&gt; want to make oodles of different horses?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then I decided to try an experiment and put all of my hard work to the test. The next morning I got up and walked straight to my computer..
(@Horse_ebooks)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;*&lt;em&gt;In a nutshell, Plato was convinced that for every concept in the world, there was an ideal form of it that existed somewhere out in the ether. This perfect, ideal form appears in our minds when we try to categorize something we see in the real world. Ex: you see a horse. Your mind contains the Platonic ideal for Horse, and your mind then matches the real, existing horse to your mental Horse, and that&#39;s how you know that what you&#39;re seeing is indeed a horse.&lt;/em&gt;&lt;/p&gt;
</description>
      <pubDate>Sat, 23 Jan 2016 16:17:00 GMT</pubDate>
      <dc:creator>Your Name</dc:creator>
      <guid>https://macroscopicentric.net/blog/object-oriented/</guid>
    </item>
  </channel>
</rss>