Compare commits

...

No commits in common. "main" and "gh-pages" have entirely different histories.

60 changed files with 30567 additions and 1268 deletions

View File

@ -1,30 +0,0 @@
name: Jekyll site CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Use GitHub Actions' cache to shorten build times and decrease load on servers
- uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile') }}
restore-keys: |
${{ runner.os }}-gems-
# Specify the target branch (optional)
- name: Jekyll Actions
uses: helaili/jekyll-action@2.2.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
keep_history: true
target_branch: 'gh-pages'

6
.gitignore vendored
View File

@ -1,6 +0,0 @@
_site
_drafts
.sass-cache
.jekyll-cache
.jekyll-metadata
vendor

0
.nojekyll 100644
View File

View File

@ -0,0 +1,649 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>First blog post - Şahin Akkayas Personal Page</title>
<meta name="description" content="Hello, World!* So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it fi…">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="First blog post">
<meta property="og:url" content="https://sahinakkaya.dev/2021/12/24/first-blog-post.html">
<meta property="og:description" content="Hello, World!* So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it fi…">
<meta property="article:published_time" content="2021-12-24T23:54:08+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2021/12/24/first-blog-post.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="First blog post">
<meta itemprop="description" content="Hello, World!* So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it fi…">
<meta itemprop="datePublished" content="2021-12-24T23:54:08+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">First blog post
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2021-12-24T23:54:08+00:00">December 24, 2021</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
3 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<style>
.ab {
font-size: 1.3em;
line-height:0;
top:0;
}
.cd {
text-decoration: none;
}
</style>
<p><em><code class="language-plaintext highlighter-rouge">Hello, World!</code></em><a href="##" title="I think I just wrote the best first sentence I could write as a programmer :D" class="cd"><sup class="ab">*</sup></a>
So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it finally have come true. You might think that I could sign-up for a social media platform and my profile would be a personal space for me but no. I just dont feel comfortable with that way. This has been the case since my childhood and also the reason why I dont use Facebook, Instagram or any other social media. If you think you found me on these platforms, I would say it is not me. I might write another post about why I dont like social media but I will cut this one here.</p>
<h2 id="why-i-wanted-to-start-blogging">Why I wanted to start blogging?</h2>
<p>There are several reasons for starting my own site and blogging, but I can list the most important ones as follows:</p>
<h3 id="giving-back-to-community">Giving back to community</h3>
<p>I use the software developed and brought by the community every day. The moment I power on my computer I start using Free Software. It really amazes me to see the work produced by people who do not know each other at all. For example, I did not even write a single line of code for this site. If Free Software didnt exist, Id either have to spend money and use a platform that I have limited control over, or waste my time and build a site with a possibly worse design than this one<a href="##" title="swh" class="cd"><sup class="ab">*</sup></a>. In return for this, I want to give back to the community. For me, the way to give back to the community so far has been to share the projects Ive done and archive the things I learn every day in a repository called <a href="https://github.com/sahinakkaya/til">TIL</a><a href="##" title="Today I Learned" class="cd"><sup class="ab">*</sup></a>. But some of the tils Ive written recently are getting lengthy and I think they deserve their own posts. So instead of writing long tils, I will blog what I learned here.</p>
<h3 id="archiving-the-memories">Archiving the memories</h3>
<p>I like to go over what I have done in the past once in a while. Blogging is perfect way to do this. I still read my diaries that I wrote in the past and they are fun. But I promise I will keep these posts more formal than my diaries<a href="##" title="swh" class="cd"><sup class="ab">*</sup></a>.</p>
<h3 id="pushing-myself-to-do-something-useful">Pushing myself to do something useful</h3>
<p>At the end of every year, I sit on my desk and think about what I did in that year. I generally dont like the result because I fail to keep some of my resolutions for that year. Setting up a personal website was one of my resolutions for 2021 and it looks like I manage to keep it<a href="##" title="hooray!" class="cd"><sup class="ab">*</sup></a><a href="##" title="swh" class="cd"><sup class="ab">*</sup></a>. Unfortunately, I cant always keep my spirits up. Sometimes I just do nothing and all the time passes. Hopefully, the feeling that I have to write something will help me get out of bad mood at such times.</p>
<h3 id="improving-my-writing-skills">Improving my writing skills</h3>
<p>Last but not least, I want to improve my writing. Even though I dont use a formal language while writing here, I think it will help me improve my writing skills.</p>
<h2 id="final-words">Final words</h2>
<p>While writing this post I already come up with some new topics to write but I think they need their own posts.</p>
<p>Subscribe to my <a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i>RSS Feed</a> to not miss them. You know RSS, right? I recently started using it and it is the best way to consume content. Do yourself a favor and search it if you dont know. I will probably write something about it in the following blog posts. Thats all from me and thank you for reading. See you next time!</p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2021-12-24T23:54:08+00:00">December 24, 2021</time></p>
</footer>
<nav class="pagination">
<a href="#" class="pagination--pager disabled">Previous</a>
<a href="/2022/01/01/stop-cat-pipeing.html" class="pagination--pager" title="Stop cat-pipeing, You Are Doing It Wrong!
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,678 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Stop cat-pipeing, You Are Doing It Wrong! - Şahin Akkayas Personal Page</title>
<meta name="description" content="cat some_file | grep some_pattern Im sure that you run a command something like above at least once if you are using terminal. You know how cat and grep works and you also know what pipe (|) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didnt know is that grep already accepts file as an argument. So the above command could be rewritten as: grep some_pattern some_file">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Stop cat-pipeing, You Are Doing It Wrong!">
<meta property="og:url" content="https://sahinakkaya.dev/2022/01/01/stop-cat-pipeing.html">
<meta property="og:description" content="cat some_file | grep some_pattern Im sure that you run a command something like above at least once if you are using terminal. You know how cat and grep works and you also know what pipe (|) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didnt know is that grep already accepts file as an argument. So the above command could be rewritten as: grep some_pattern some_file">
<meta property="article:published_time" content="2022-01-01T15:00:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/01/01/stop-cat-pipeing.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Stop cat-pipeing, You Are Doing It Wrong!">
<meta itemprop="description" content="cat some_file | grep some_patternIm sure that you run a command something like above at least once if you are using terminal. You know how cat and grep works and you also know what pipe (|) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didnt know is that grep already accepts file as an argument. So the above command could be rewritten as:grep some_pattern some_file">
<meta itemprop="datePublished" content="2022-01-01T15:00:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Stop cat-pipeing, You Are Doing It Wrong!
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-01-01T15:00:00+00:00">January 1, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat </span>some_file | <span class="nb">grep </span>some_pattern
</code></pre></div></div>
<p>Im sure that you run a command something like above at least once if you are using terminal. You know how <code class="language-plaintext highlighter-rouge">cat</code> and <code class="language-plaintext highlighter-rouge">grep</code> works and you also know what pipe (<code class="language-plaintext highlighter-rouge">|</code>) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didnt know is that <code class="language-plaintext highlighter-rouge">grep</code> already accepts file as an argument. So the above command could be rewritten as:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep </span>some_pattern some_file
</code></pre></div></div>
<p>… which can make you save a few keystrokes and a few nanoseconds of CPU cycles. Phew! Not a big deal if you are not working files that contains GBs of data, right? I agree but you should still use the latter command because it will help you solve some other problems better. Here is a real life scenario: You want to search for some specific pattern in all the files in a directory.</p>
<ul>
<li>If you use the first approach, you may end up running commands like this:</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">ls</span>
 config.lua  Git.lua  init.lua  markdown.lua  palette.lua  util.lua
 diff.lua  highlights.lua  LSP.lua  Notify.lua  Treesitter.lua  Whichkey.lua
<span class="nb">cat </span>config.lua | <span class="nb">grep </span>light
<span class="nb">cat </span>diff.lua | <span class="nb">grep </span>light
<span class="nb">cat </span>Git.lua | <span class="nb">grep </span>light
<span class="nb">cat </span>highlights.lua | <span class="nb">grep </span>light
Pmenu <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.popup_back <span class="o">}</span>,
CursorLineNr <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, style <span class="o">=</span> <span class="s2">"bold"</span> <span class="o">}</span>,
Search <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.search_blue <span class="o">}</span>,
IncSearch <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.search_blue <span class="o">}</span>,
<span class="nb">cat </span>init.lua | <span class="nb">grep </span>light
<span class="nb">local </span>highlights <span class="o">=</span> require <span class="s2">"onedarker.highlights"</span>
highlights,
<span class="c"># You still have a lot to do :/</span>
</code></pre></div></div>
<ul>
<li>If you use the second approach, you will immediately realize that you can send all the files with <code class="language-plaintext highlighter-rouge">*</code> operator and you will finish the job with just one command (2 if you include mandatory <code class="language-plaintext highlighter-rouge">ls</code> :D):</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">ls</span>
 config.lua  Git.lua  init.lua  markdown.lua  palette.lua  util.lua
 diff.lua  highlights.lua  LSP.lua  Notify.lua  Treesitter.lua  Whichkey.lua
<span class="nb">grep </span>light <span class="k">*</span>
highlights.lua: Pmenu <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.popup_back <span class="o">}</span>,
highlights.lua: CursorLineNr <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, style <span class="o">=</span> <span class="s2">"bold"</span> <span class="o">}</span>,
highlights.lua: Search <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.search_blue <span class="o">}</span>,
highlights.lua: IncSearch <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.search_blue <span class="o">}</span>,
init.lua:local highlights <span class="o">=</span> require <span class="s2">"onedarker.highlights"</span>
init.lua: highlights,
LSP.lua: NvimTreeNormal <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.alt_bg <span class="o">}</span>,
LSP.lua: LirFloatNormal <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray, <span class="nb">bg</span> <span class="o">=</span> C.alt_bg <span class="o">}</span>,
markdown.lua: markdownIdDelimiter <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray <span class="o">}</span>,
markdown.lua: markdownLinkDelimiter <span class="o">=</span> <span class="o">{</span> <span class="nb">fg</span> <span class="o">=</span> C.light_gray <span class="o">}</span>,
palette.lua: light_gray <span class="o">=</span> <span class="s2">"#abb2bf"</span>,
palette.lua: light_red <span class="o">=</span> <span class="s2">"#be5046"</span>,
util.lua:local <span class="k">function </span>highlight<span class="o">(</span>group, properties<span class="o">)</span>
util.lua: <span class="s2">"highlight"</span>,
util.lua: highlight<span class="o">(</span>group, properties<span class="o">)</span>
</code></pre></div></div>
<p>Isnt this neat? You might say that <em>“This is cheating! You are using a wild card, of course it will be easier.”</em> Well, yes. Technically I could use the same wild card in the first command like <code class="language-plaintext highlighter-rouge">cat * | grep light</code> but:</p>
<ul>
<li>I figured that out only after using wild card in the second command. So I think it is does not feel natural.</li>
<li>It is still not giving the same output. Try and see the difference! <a href="##" title="You will not be able to see which file contains which line. 'cat' will just concatenate all the input.">*</a>
</li>
</ul>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-01-01T15:00:00+00:00">January 1, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2021/12/24/first-blog-post.html" class="pagination--pager" title="First blog post
">Previous</a>
<a href="/2022/01/04/build-and-deploy-automatically.html" class="pagination--pager" title="Automatically Build and Deploy Your Site using GitHub Actions and Webhooks
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,800 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Automatically Build and Deploy Your Site using GitHub Actions and Webhooks - Şahin Akkayas Personal Page</title>
<meta name="description" content="In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Automatically Build and Deploy Your Site using GitHub Actions and Webhooks">
<meta property="og:url" content="https://sahinakkaya.dev/2022/01/04/build-and-deploy-automatically.html">
<meta property="og:description" content="In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.">
<meta property="article:published_time" content="2022-01-04T17:40:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/01/04/build-and-deploy-automatically.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Automatically Build and Deploy Your Site using GitHub Actions and Webhooks">
<meta itemprop="description" content="In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.">
<meta itemprop="datePublished" content="2022-01-04T17:40:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Automatically Build and Deploy Your Site using GitHub Actions and Webhooks
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-01-04T17:40:00+00:00">January 4, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<p>In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.</p>
<h2 id="introduction-to-github-actions-and-webhooks">Introduction to GitHub Actions and Webhooks</h2>
<p>Let me start by explaining what are GitHub Actions and GitHub Webhooks.</p>
<blockquote>
<p><strong>Github Actions</strong> is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.</p>
</blockquote>
<blockquote>
<p><strong>Webhooks</strong> provide a way for notifications to be delivered to an external web server whenever certain actions occur on a repository or organization. … For example, you can configure a webhook to execute whenever:</p>
<ul>
<li>A repository is pushed to</li>
<li>A pull request is opened</li>
<li>A GitHub Pages site is built</li>
<li>A new member is added to a team</li>
</ul>
</blockquote>
<h2 id="defining-the-problem-and-solution">Defining the problem and solution</h2>
<p>As I said, my example will be automating the deployment of this site. Here is the normal workflow of me doing it manually:
<img src="/assets/images/gh-actions-and-webhooks/workflow.png" alt="My workflow"></p>
<p>As you can see, the only place where my work is really required is writing the post. Other two steps can be automated. We will use GitHub Actions to generate the site content and Webhooks to let our server know about the new content so it can pull the changes. Lets get started.</p>
<h3 id="setting-up-github-actions">Setting up GitHub Actions</h3>
<p>Setting up a GitHub Action is as easy as creating a <code class="language-plaintext highlighter-rouge">.yml</code> file in <code class="language-plaintext highlighter-rouge">.github/workflows/</code> directory in your repository. Let us create a new action to build our site. Fortunately, there is already a <a href="https://github.com/marketplace/actions/jekyll-actions">GitHub action</a> to do it for us. Create a file called <code class="language-plaintext highlighter-rouge">.github/workflows/jekyll.yml</code> in your root directory of your repository and put the following contents:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s">Jekyll site CI</span>
<span class="na">on</span><span class="pi">:</span>
<span class="na">push</span><span class="pi">:</span>
<span class="na">branches</span><span class="pi">:</span> <span class="pi">[</span> <span class="nv">main</span> <span class="pi">]</span>
<span class="na">pull_request</span><span class="pi">:</span>
<span class="na">branches</span><span class="pi">:</span> <span class="pi">[</span> <span class="nv">main</span> <span class="pi">]</span>
<span class="na">jobs</span><span class="pi">:</span>
<span class="na">build</span><span class="pi">:</span>
<span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-latest</span>
<span class="na">steps</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v2</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Jekyll Actions</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">helaili/jekyll-action@2.2.0</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">token</span><span class="pi">:</span> <span class="s">${{ secrets.GITHUB_TOKEN }}</span>
<span class="na">keep_history</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">target_branch</span><span class="pi">:</span> <span class="s1">'</span><span class="s">gh-pages'</span>
</code></pre></div></div>
<p>Thats it! We have created our first Action. When we push this change, GitHub will start building our site and push the result to <code class="language-plaintext highlighter-rouge">gh-pages</code> branch. Currently, it will take a while to build because we dont use caching. So lets include it to build faster. Add the following piece as a second step:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Use GitHub Actions' cache to shorten build times and decrease load on servers</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/cache@v2</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">path</span><span class="pi">:</span> <span class="s">vendor/bundle</span>
<span class="na">key</span><span class="pi">:</span> <span class="s">${{ runner.os }}-gems-${{ hashFiles('**/Gemfile') }}</span>
<span class="na">restore-keys</span><span class="pi">:</span> <span class="pi">|</span>
<span class="s">${{ runner.os }}-gems-</span>
</code></pre></div></div>
<p>We are done with the Actions part. You can see the final code <a href="https://github.com/sahinakkaya/sahinakkayadotdev/blob/main/.github/workflows/jekyll.yml">here</a>. When you are also done with the code, just push it to trigger the action.</p>
<h3 id="setting-up-the-webhook-and-related-endpoint">Setting up the Webhook and related endpoint</h3>
<p>Now that we set up our Action to build the site, we need to let our server know about the changes so that it can pull the changes.</p>
<h4 id="creating-a-webhook-from-github">Creating a Webhook from GitHub</h4>
<p>To add a Webhook, open your repository in browser and navigate to <em>Settings &gt; Webhooks</em> and click <em>Add Webhook</em>. Fill in the form with appropriate values. Here is an example:
<img src="/assets/images/gh-actions-and-webhooks/add-webhook.png" alt="Webhook form example"></p>
<p>This is all you have to do from GitHub. Now, whenever there is a <em><code class="language-plaintext highlighter-rouge">push</code></em> event to your repository, GitHub will send a POST request to your <em>payload url</em> with the details.</p>
<p class="notice--info"><strong>Note:</strong> Our Action is configured to push to a branch in our repository, so it will also trigger this hook and we will catch it.</p>
<h4 id="creating-an-endpoint-to-handle-the-requests">Creating an endpoint to handle the requests</h4>
<p>I will use <a href="https://flask.palletsprojects.com/en/2.0.x/">Flask</a> framework to handle the post requests coming to our endpoint. You can use whatever programming language or framework you want. It will be very simple code with just one job: Validate the secret keys and run a specific code.</p>
<p>Lets start by creating a new project and a virtual environment:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdkir post_receiver
<span class="nb">cd </span>post_receiver
python3 <span class="nt">-m</span> venv venv
<span class="nb">source </span>venv/bin/activate
</code></pre></div></div>
<p>Install the required packages:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>Flask gunicorn
</code></pre></div></div>
<p>Create a new file for storing our environment variables:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># config.py
</span>
<span class="n">APP_KEY</span> <span class="o">=</span> <span class="s">"your-secret-key"</span> <span class="c1"># same key that is used in github while creating the webhook
</span><span class="n">PROJECT_PATH</span> <span class="o">=</span> <span class="s">"/path/to/your/project/"</span> <span class="c1"># you will want to cd into this path and perform commands such as git pull etc.
</span></code></pre></div></div>
<p>And create the Flask application:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># post_receiver.py
</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">import</span> <span class="nn">hmac</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">request</span>
<span class="kn">import</span> <span class="nn">config</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<span class="o">@</span><span class="n">application</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s">'GET'</span><span class="p">,</span> <span class="s">'POST'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
<span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">'GET'</span><span class="p">:</span>
<span class="k">return</span> <span class="s">'OK'</span>
<span class="k">elif</span> <span class="n">request</span><span class="p">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">'POST'</span><span class="p">:</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">data</span>
<span class="n">secret</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">config</span><span class="p">.</span><span class="n">APP_KEY</span><span class="p">,</span> <span class="s">'utf-8'</span><span class="p">)</span>
<span class="n">digester</span> <span class="o">=</span> <span class="n">hmac</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">secret</span><span class="p">,</span> <span class="n">content</span><span class="p">,</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">sha256</span><span class="p">)</span>
<span class="n">calculated_signature</span> <span class="o">=</span> <span class="s">'sha256='</span> <span class="o">+</span> <span class="n">digester</span><span class="p">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="n">actual_signature</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">headers</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'X-Hub-Signature-256'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">calculated_signature</span> <span class="o">==</span> <span class="n">actual_signature</span><span class="p">:</span>
<span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span>
<span class="p">[</span><span class="s">'./perform-git-pull.sh'</span><span class="p">,</span> <span class="n">config</span><span class="p">.</span><span class="n">PROJECT_PATH</span><span class="p">])</span>
<span class="k">return</span> <span class="s">'OK'</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">'Error'</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">application</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">'0.0.0.0'</span><span class="p">)</span>
</code></pre></div></div>
<p>I will not go into details explaining what each line does. Basically, we are checking if the request is a POST request and if so we are comparing the secret keys to make sure that the request is coming from GitHub. In our case, this is not too important because when the keys match we are running simple git commands in our repository but you might need it if you are doing something more complicated. And here is the contents of <code class="language-plaintext highlighter-rouge">perform-git-pull.sh</code> file:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="nb">cd</span> <span class="nv">$1</span>
git checkout gh-pages
git pull
</code></pre></div></div>
<p>We are almost done! All we need to do is create a service to automatically run our code and let nginx handle our endpoint correctly.</p>
<p>Create a new file <code class="language-plaintext highlighter-rouge">post_receiver.service</code> in <code class="language-plaintext highlighter-rouge">/etc/systemd/system/</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#/etc/systemd/system/post_receiver.service
# change &lt;user&gt; to your actual username
[Unit]
Description=post_receiver
After=network.target multi-user.target
[Service]
User=&lt;user&gt;
Environment="PYTHONPATH=/home/&lt;user&gt;/post_receiver/venv/bin/python"
WorkingDirectory=/home/&lt;user&gt;/post_receiver
ExecStart=/home/&lt;user&gt;/post_receiver/venv/bin/gunicorn -b 127.0.0.1:5000 -w 2 --log-file /home/&lt;user&gt;/post_receiver/post_receiver.log post_receiver
[Install]
WantedBy=multi-user.target
</code></pre></div></div>
<p>Make sure port <code class="language-plaintext highlighter-rouge">5000</code> is reachable from outside.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>ufw allow 5000
<span class="nb">sudo </span>ufw <span class="nb">enable</span>
</code></pre></div></div>
<p>Finally, edit your nginx configuration, <code class="language-plaintext highlighter-rouge">/etc/nginx/sites-available/yoursite</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>location = /postreceive/ {
proxy_pass http://localhost:5000/;
}
</code></pre></div></div>
<p>Start, restart the services</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl daemon-reload
<span class="nb">sudo </span>systemctl start post_receiver
<span class="nb">sudo </span>systemctl <span class="nb">enable </span>post_receiver
<span class="nb">sudo </span>systemctl restart nginx
</code></pre></div></div>
<p>Thats it! <code class="language-plaintext highlighter-rouge">curl https://yourdomain.com/postreceive/</code> should return <code class="language-plaintext highlighter-rouge">"OK"</code> and we are ready to accept POST requests from GitHub.</p>
<h3 id="notes-for-debugging">Notes for debugging</h3>
<p>In case anything goes wrong, here are a few tips to debug:</p>
<ul>
<li>Every GitHub Action produces a log that you can examine. Check them to see if anything is odd.</li>
<li>In the <em>Webhooks</em> tab, there is a sub-tab called <em>Recent Deliveries</em>. You can take a look at there to see the results of the requests from your hooks.</li>
<li>You can always test your code locally with <code class="language-plaintext highlighter-rouge">curl</code>:
<div class="language-plaintext highlighter-rouge">
<div class="highlight"><pre class="highlight"><code> curl -i -X POST -H 'Content-Type: application/json' -d '{"foo": "bar", "bar": "baz"}' https://yourdomain.com/postreceive/
</code></pre></div> </div>
</li>
</ul>
<p>Happy hacking!</p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-01-04T17:40:00+00:00">January 4, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/01/01/stop-cat-pipeing.html" class="pagination--pager" title="Stop cat-pipeing, You Are Doing It Wrong!
">Previous</a>
<a href="/2022/01/21/ffmpeg-to-rescue.html" class="pagination--pager" title="Using ffmpeg for Simple Video Editing
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,638 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Using ffmpeg for Simple Video Editing - Şahin Akkayas Personal Page</title>
<meta name="description" content="Story Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up Kdenlive and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give ffmpeg a shot.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Using ffmpeg for Simple Video Editing">
<meta property="og:url" content="https://sahinakkaya.dev/2022/01/21/ffmpeg-to-rescue.html">
<meta property="og:description" content="Story Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up Kdenlive and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give ffmpeg a shot.">
<meta property="article:published_time" content="2022-01-21T20:40:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/01/21/ffmpeg-to-rescue.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Using ffmpeg for Simple Video Editing">
<meta itemprop="description" content="StoryToday, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up Kdenlive and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give ffmpeg a shot.">
<meta itemprop="datePublished" content="2022-01-21T20:40:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Using ffmpeg for Simple Video Editing
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-01-21T20:40:00+00:00">January 21, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<h2 id="story">Story</h2>
<p>Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up <a href="https://kdenlive.org/en/">Kdenlive</a> and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give <code class="language-plaintext highlighter-rouge">ffmpeg</code> a shot.</p>
<h2 id="let-the-show-begin">Let the show begin</h2>
<p>Like Kdenlive, I have never used <code class="language-plaintext highlighter-rouge">ffmpeg</code> before. Like every normal Linux user do, I opened up a terminal and typed <code class="language-plaintext highlighter-rouge">man ffmpeg</code> to learn how to use it… Just kidding :D I opened a browser and typed <em>“ffmpeg cut video by time”</em>. Not the best search query, but it was good enough to find what I am looking for as the <a href="https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg">first result</a>.</p>
<h3 id="cutting-the-videos-based-on-start-and-end-time">Cutting the videos based on start and end time</h3>
<p>According to answers on the page I mentioned, I run the following commands to cut my video into two parts:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ffmpeg <span class="nt">-ss</span> 00:00:00 <span class="nt">-to</span> 00:01:55 <span class="nt">-i</span> input.mov <span class="nt">-c</span> copy part1.mp4 <span class="c"># take from 00:00 to 01:55</span>
ffmpeg <span class="nt">-ss</span> 00:02:03 <span class="nt">-to</span> 00:05:17 <span class="nt">-i</span> input.mov <span class="nt">-c</span> copy part2.mp4 <span class="c"># take from 02:03 to 05:17</span>
</code></pre></div></div>
<p>These two commands run <strong>instantly</strong>! Kdenlive was still rendering… The progress was 46%. Meh… I said “Duck it, I am gonna use ffmpeg only” and cancelled the rendering.</p>
<h3 id="concatenating-the-video-files">Concatenating the video files</h3>
<p>Now we have two videos that we want to join. Guess what will be our next search query? <em>“ffmpeg join videos”</em>. And <a href="https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg">here</a> is the first result:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo </span>file part1.mp4 <span class="o">&gt;&gt;</span> mylist.txt
<span class="nb">echo </span>file part2.mp4 <span class="o">&gt;&gt;</span> mylist.txt
ffmpeg <span class="nt">-f</span> concat <span class="nt">-i</span> mylist.txt <span class="nt">-c</span> copy result.mp4
</code></pre></div></div>
<p>And we are DONE! How easy was that? Whole process took about 10 minutes including my search on the internet. If I continued waiting for Kdenlive to finish rendering, I would probably be still waiting at that time. I love the power of command line!</p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-01-21T20:40:00+00:00">January 21, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/01/04/build-and-deploy-automatically.html" class="pagination--pager" title="Automatically Build and Deploy Your Site using GitHub Actions and Webhooks
">Previous</a>
<a href="/2022/02/26/ssh-into-machine-that-is-behind-private-network.html" class="pagination--pager" title="SSH into Machine That Is Behind a Private Network
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,658 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>SSH into Machine That Is Behind a Private Network - Şahin Akkayas Personal Page</title>
<meta name="description" content="Story I believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="SSH into Machine That Is Behind a Private Network">
<meta property="og:url" content="https://sahinakkaya.dev/2022/02/26/ssh-into-machine-that-is-behind-private-network.html">
<meta property="og:description" content="Story I believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.">
<meta property="article:published_time" content="2022-02-26T21:40:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/02/26/ssh-into-machine-that-is-behind-private-network.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="SSH into Machine That Is Behind a Private Network">
<meta itemprop="description" content="StoryI believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.">
<meta itemprop="datePublished" content="2022-02-26T21:40:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">SSH into Machine That Is Behind a Private Network
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-02-26T21:40:00+00:00">February 26, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<h2 id="story">Story</h2>
<p>I believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.</p>
<h2 id="possible-solutions">Possible solutions</h2>
<ul>
<li>
<p>Just tell the non-tech people at home to configure the router to forward ssh traffic to desktop, right? Well, this is not an option for me, not because people are non-tech, but there is no router! The desktop is connected to internet via hotspot from mobile phone. There is no root access in the phone and even if there was, it is a really big pain to forward the packets manually. Trust me. Been there, done that!</p>
</li>
<li>
<p>There are tools like <a href="https://www.ngrok.com">ngrok</a>, <a href="localtunnel.me">localtunnel</a> which exposes your localhost to the internet and gives you a URL to access it but I did not want to use them.</p>
<ul>
<li>I did not want to use <code class="language-plaintext highlighter-rouge">ngrok</code> because it is not open source and it might have security issues. They are also charging you.</li>
<li>
<code class="language-plaintext highlighter-rouge">localtunnel</code> seemed perfect. The code of both client and server is open. That is great news! But it did not last long because it is just forwarding http/https traffic :(</li>
</ul>
</li>
</ul>
<h2 id="solution">Solution</h2>
<p>I was thinking of extending the functionality of <code class="language-plaintext highlighter-rouge">localtunnel</code>, but I learned a very simple way. You dont need any external program to overcome this issue. The good old <code class="language-plaintext highlighter-rouge">ssh</code> can do that! All you need is another machine (a remote server) that both computers can access via ssh.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># local machine (my home computer)</span>
ssh <span class="nt">-R</span> 7777:localhost:22 remote-user@remote.host
</code></pre></div></div>
<p>This command forwards all the incoming connections to port 7777 of remote machine to port 22 of our current machine. In order for this to work, you need to make sure <code class="language-plaintext highlighter-rouge">GatewayPorts</code> is set to <code class="language-plaintext highlighter-rouge">yes</code> in the remote server ssh configuration. It also assumes our current machine accepts ssh connections via port 22.</p>
<hr>
<p>Now, go to any machine and connect to the remote server first. When we are connected, we will create another ssh connection to port 7777 to connect our home computer.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># another local machine (my laptop)</span>
ssh remote-user@remote.host
<span class="c"># connected remote</span>
ssh <span class="nt">-p</span> 7777 homeuser@localhost
<span class="c"># we are now connected to home computer</span>
</code></pre></div></div>
<p>The last two command can also combined so that we directly hop into the home computer.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-t</span> remote-user@remote.host ssh <span class="nt">-p</span> 7777 homeuser@localhost
</code></pre></div></div>
<h3 id="result">Result</h3>
<p>As a result, it only took us 2 simple ssh commands to do this. This is just unbelievable! Now, I need to find a way to make non-tech people at home run this command when there is a problem. Too bad Linux cant help me there :D</p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-02-26T21:40:00+00:00">February 26, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/01/21/ffmpeg-to-rescue.html" class="pagination--pager" title="Using ffmpeg for Simple Video Editing
">Previous</a>
<a href="/2022/02/27/creating-a-useless-user.html" class="pagination--pager" title="Creating a Useless User
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,648 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Creating a Useless User - Şahin Akkayas Personal Page</title>
<meta name="description" content="Story In my previous post, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriends computer. Now, of course I dont want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Creating a Useless User">
<meta property="og:url" content="https://sahinakkaya.dev/2022/02/27/creating-a-useless-user.html">
<meta property="og:description" content="Story In my previous post, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriends computer. Now, of course I dont want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.">
<meta property="article:published_time" content="2022-02-27T13:40:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/02/27/creating-a-useless-user.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Creating a Useless User">
<meta itemprop="description" content="StoryIn my previous post, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriends computer. Now, of course I dont want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.">
<meta itemprop="datePublished" content="2022-02-27T13:40:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Creating a <em>Useless</em> User
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-02-27T13:40:00+00:00">February 27, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<h2 id="story">Story</h2>
<p>In my <a href="/2022/02/26/ssh-into-machine-that-is-behind-private-network.html">previous post</a>, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriends computer. Now, of course I dont want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.</p>
<h2 id="the-solution">The solution</h2>
<p>I searched the problem in it turned out to be very simple. You just need to add two additional flags to <code class="language-plaintext highlighter-rouge">adduser</code> command while creating the user.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>adduser uselessuser <span class="nt">--shell</span><span class="o">=</span>/bin/false <span class="nt">--no-create-home</span>
</code></pre></div></div>
<p>Now, <code class="language-plaintext highlighter-rouge">uselessuser</code> cant do anything useful in your server. If they try to login, the connection will be closed immediately.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ssh uselessuser@remote.host
uselessuser@remote.host<span class="se">\'</span>s password:
Could not chdir to home directory /home/uselessuser: No such file or directory
Connection to remote.host closed.
</code></pre></div></div>
<p>But they can still do forward the remote port to their local machine.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ssh <span class="nt">-Nf</span> <span class="nt">-R</span> 7777:localhost:22 uselessuser@remote.host
uselessuser@remote.host<span class="se">\'</span>s password:
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">-N</code> option is the most important one here. From the documentation:</p>
<blockquote>
<div class="language-plaintext highlighter-rouge">
<div class="highlight"><pre class="highlight"><code> -N Do not execute a remote command. This is useful
for just forwarding ports. Refer to the description
of SessionType in ssh_config(5) for details.
</code></pre></div> </div>
</blockquote>
<h2 id="last-words">Last words</h2>
<p>I love learning new things everyday. I knew setting the shell of a user to <code class="language-plaintext highlighter-rouge">/bin/false</code> will prevent them from logging in. The reason I wrote this blog post is because 2 things I wanted to share:</p>
<ul>
<li>While looking for a solution to the problem I mentioned, I searched <em>“create a user with no privileges in linux”</em> and <a href="https://askubuntu.com/questions/1174376/how-to-create-a-user-with-the-least-privileges-permissions-but-enough-to-do-ssh">this</a> came out. It is really interesting for me that another person wanted to do the same thing for the <em>exact same reasons</em>. They were also trying port forwarding via ssh and they wanted to create a limited user in their server to give friends. So the question was a <strong>perfect fit</strong> to the problem.</li>
<li>The <code class="language-plaintext highlighter-rouge">-N</code> flag of the ssh command was also surprising for me. It was like as if someone had encountered these problems before and just took the exact steps required to solve this problem for me. I mean look at the documentation. Crazy!</li>
</ul>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-02-27T13:40:00+00:00">February 27, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/02/26/ssh-into-machine-that-is-behind-private-network.html" class="pagination--pager" title="SSH into Machine That Is Behind a Private Network
">Previous</a>
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" class="pagination--pager" title="Never Get Trapped in Grub Rescue Again!
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,685 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Never Get Trapped in Grub Rescue Again! - Şahin Akkayas Personal Page</title>
<meta name="description" content="Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” menu and I dont know how to fix things from that point.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Never Get Trapped in Grub Rescue Again!">
<meta property="og:url" content="https://sahinakkaya.dev/2022/03/03/never-get-trapped-in-grub-rescue-again.html">
<meta property="og:description" content="Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” menu and I dont know how to fix things from that point.">
<meta property="article:published_time" content="2022-03-03T00:46:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/03/03/never-get-trapped-in-grub-rescue-again.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Never Get Trapped in Grub Rescue Again!">
<meta itemprop="description" content="Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” menu and I dont know how to fix things from that point.">
<meta itemprop="datePublished" content="2022-03-03T00:46:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Never Get Trapped in Grub Rescue Again!
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
4 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<p>Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” menu and I dont know how to fix things from that point.</p>
<p>I go into the live environment and run some random commands that I found on the internet and hope for the best.</p>
<p><img src="/assets/images/grub-rescue/random-bullshit.jpg" alt="me trying to fix grub"></p>
<p>What a nice way to shoot myself in the foot! But this time is different. This time, I f*cked up so much that even the random commands on the internet could not help me. I was on my own and I needed to figure out what is wrong with my system. Let me tell you what I did:</p>
<p>I decided to install another OS just to try it in a real machine. I wanted to shrink one of my partitions to create a space for the new system. I run <code class="language-plaintext highlighter-rouge">fdisk /dev/sdb</code>, the very first message that it tells me was</p>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">This disk is currently in use - repartitioning is probably a bad idea. It's recommended to umount all file systems, and swapoff all swap partitions on this disk.</code></p>
</blockquote>
<p>Yes, it just screams <strong><em>“Do not do it!”</em></strong> but come on. I will not try to shrink the partition I am using (<code class="language-plaintext highlighter-rouge">sdb3</code>). So it should not be a problem. I ignored the message and shrink it anyway. No problem. Installed and tested the new OS a little bit. Time to reboot and hope for the best. And of course it did not boot. What would I even expecting?</p>
<p><img src="/assets/images/grub-rescue/cj.png" alt="ah sh*t here we go again"></p>
<p>As always, I booted into a live environment and run <code class="language-plaintext highlighter-rouge">boot-repair</code> command. It was always working but this time… Even after finishing the operation successfully I could not boot into neither Arch nor Ubuntu (the two systems I had previously).</p>
<p>Arch was originally mounted in <code class="language-plaintext highlighter-rouge">sdb3</code> and Ubuntu was in <code class="language-plaintext highlighter-rouge">sda2</code>. Considering the fact that I only messed with <code class="language-plaintext highlighter-rouge">sdb</code>, I should be able to boot Ubuntu, right? Well, yeah. Technically I did boot into Ubuntu but I didnt see the login screen. It was dropping me into something called <em>“Emergency mode”</em> which just makes me panic! <code class="language-plaintext highlighter-rouge">sudo update-grub</code>… Nope. Nothing changes. Arch does not boot and Ubuntu partially boots.</p>
<p>Let me tell you what the problem was and how my ignorance made it worse:</p>
<ul>
<li>
<p>While installing the new system, I saw a partition <strong>labelled</strong> <em>“Microsoft Basic Data”</em>. I deleted it thinking it is not required because I dont use W*ndows. It turns out, it was my <em>boot</em> partition for Arch, just labelled incorrectly… Big lolz :D But we will see this is not even important because I had to rewrite my boot partition anyway.</p>
</li>
<li>My Arch was installed in <code class="language-plaintext highlighter-rouge">sdb3</code>. When I created a new partition and installed the new system, <code class="language-plaintext highlighter-rouge">sdb3</code> was shifted to <code class="language-plaintext highlighter-rouge">sdb5</code> even though I did not ask for it. But the grub configuration to boot my system was still pointing to <code class="language-plaintext highlighter-rouge">sdb3</code>. That was the reason why Arch does not boot. It was trying to boot from <code class="language-plaintext highlighter-rouge">sdb3</code>. So I had to recreate grub configuration and reinstall grub to fix it. I run the following commands that I found <a href="https://www.jeremymorgan.com/tutorials/linux/how-to-reinstall-boot-loader-arch-linux/">here</a> in a live Arch environment:
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> /mnt/arch
mount <span class="nt">-t</span> auto /dev/sdb5 /mnt/arch
arch-chroot /mnt/arch
mount <span class="nt">-t</span> auto /dev/sdb4 /boot/efi
os-prober
grub-mkconfig <span class="o">&gt;</span> /boot/grub/grub.cfg
grub-install <span class="nt">--efi-directory</span><span class="o">=</span>/boot/efi <span class="nt">--target</span><span class="o">=</span>x86_64-efi /dev/sdb
<span class="nb">exit
</span>reboot
</code></pre></div> </div>
<p>And it fixed my grub. I can now boot into Arch, hooray!</p>
</li>
<li>
<p>Ubuntu was not still booting properly. I checked the logs with <code class="language-plaintext highlighter-rouge">journalctl -xb</code> and saw something related with <code class="language-plaintext highlighter-rouge">sdb</code>. Ubuntu was installed in <code class="language-plaintext highlighter-rouge">sda2</code>, why <code class="language-plaintext highlighter-rouge">sdb</code> should be a problem? Then I remembered something. Back in times when I was using Ubuntu, I was using <code class="language-plaintext highlighter-rouge">sdb1</code> as a secondary storage. So I had a configuration where it automatically mounts <code class="language-plaintext highlighter-rouge">sdb1</code> on startup. Since I messed with <code class="language-plaintext highlighter-rouge">sdb1</code> , it was failing to mount it. I opened <code class="language-plaintext highlighter-rouge">/etc/fstab</code>, and deleted the related line. Bingo! It started booting properly.</p>
<p><img src="/assets/images/grub-rescue/hackerman.jpg" alt="i am something of a hackerman myself"></p>
</li>
<li>
<p>I started feeling like Hackerman, and I said to myself <em>“You know what, Imma fix everything.”</em> I had a very sh*tty grub menu with useless grub entries from old systems that I dont use anymore. The UEFI also had the same problem. It had ridiculous amount of boot entries that most of them are just trash.</p>
<p><img src="/assets/images/grub-rescue/shitty-uefi.jpg" alt="the pictures i took while trying to figure out which boot options are useless"></p>
<p>These are the pictures I took for reference while trying to figure out which boot options are useless. Sorry for the bad quality. I didnt think I would use them in a blog post.</p>
<ul>
<li>While trying to fix the previous problems, Ive spent enough time in the <code class="language-plaintext highlighter-rouge">/boot/efi</code> directory that make me understand where these grub entries are coming from. There were a lot of files belong to old systems. I simply deleted them and updated grub. All of the bad entries were gone. I want to draw your attention here: <em>I did not search for how to delete the unused grub entries. I just knew deleting their directories from <code class="language-plaintext highlighter-rouge">/boot/efi</code> will do the job. I am doing this sh*t! (Another hackerman moment :D )</em>
</li>
<li>In order to delete useless boot options from UEFI menu, I used <code class="language-plaintext highlighter-rouge">efibootmgr</code>. I searched for it on the internet, of course!
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>efibootmgr <span class="nt">-v</span> <span class="c"># Check which entries you want to delete, say it is 0003.</span>
<span class="nb">sudo </span>efibootmgr <span class="nt">-b</span> 0003 <span class="nt">-B</span> <span class="c"># This will delete third boot option. </span>
</code></pre></div> </div>
</li>
</ul>
</li>
</ul>
<p>And finally! I know everything about how all these work. Another shady part of Linux is clear for me. Now:</p>
<p><img src="/assets/images/grub-rescue/quote.jpg" alt="Give me a ruined computer and an Arch ISO, and I shall fix it for you."></p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/02/27/creating-a-useless-user.html" class="pagination--pager" title="Creating a Useless User
">Previous</a>
<a href="/2022/04/08/confession-time.html" class="pagination--pager" title="Confession Time
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,639 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Confession Time - Şahin Akkayas Personal Page</title>
<meta name="description" content="A failure story Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I cant send or receive any emails. If you send me email in the last week and wonder why I didnt respond, this is the reason.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Confession Time">
<meta property="og:url" content="https://sahinakkaya.dev/2022/04/08/confession-time.html">
<meta property="og:description" content="A failure story Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I cant send or receive any emails. If you send me email in the last week and wonder why I didnt respond, this is the reason.">
<meta property="article:published_time" content="2022-04-08T15:46:00+00:00">
<meta property="article:modified_time" content="2022-04-13T00:00:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/04/08/confession-time.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Confession Time">
<meta itemprop="description" content="A failure storyLast week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I cant send or receive any emails. If you send me email in the last week and wonder why I didnt respond, this is the reason.">
<meta itemprop="datePublished" content="2022-04-08T15:46:00+00:00">
<meta itemprop="dateModified" content="2022-04-13T00:00:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Confession Time
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<h2 id="a-failure-story">A failure story</h2>
<p>Last week, I received an email from <a href="https://letsencrypt.org/">Lets Encrypt</a> reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I cant send or receive any emails. If you send me email in the last week and wonder why I didnt respond, this is the reason.</p>
<p>Anyway, I thought it will be easy to fix. Just run <code class="language-plaintext highlighter-rouge">certbot</code> again and let him do the job, right? NOPE. It is not that easy. It is just giving me errors with some success messages. If I was not so clueless about what the heck I am doing, I could fix the error. But I dont know anything about how SSL works and it is a shame.</p>
<p>I dont even know the subject enough to Google it. I feel like I am the only guy in the planet whose certificate is expired. Seriously, how tf I cant find a solution to a such common problem? There was a saying like, <em>“If you cant find something on the internet, there is a high chance that you are being stupid”</em>. It was not exactly like this but I cant find the original quote either. Argghh…</p>
<p>If you know the original quote, email me… No, do not email because it does not work. F%ck this thing. F*%k everything. I deserved this. Do not help. If I cant fix this by myself, I should not call myself computer engineer. I am out.</p>
<h3 id="update"><strong>Update</strong></h3>
<p>The problem is fixed. One of my colleagues told me to reboot the server so that it will (<em>possibly</em>) trigger a script to get a new certificate. I did not think it would work because I already try to get a new certificate manually running <code class="language-plaintext highlighter-rouge">certbot renew</code>. And yeah, it didnt change anything but gave me courage to try other <em>dead simple</em> solutions.</p>
<ul>
<li>
<p>One of them was adding missing MX records for my domain. <code class="language-plaintext highlighter-rouge">certbot</code> was telling me that it cant find any <code class="language-plaintext highlighter-rouge">A</code> or <code class="language-plaintext highlighter-rouge">AAAA</code> records for <code class="language-plaintext highlighter-rouge">www.mail</code>. I didnt think this is related with my problem because how would I receive emails before then? Anyway, I added the records and the errors are gone. It was only giving me success messages now. Everything seemed to be fine. But I still could not connect to my mail account.</p>
</li>
<li>
<p>And here is the solution: <code class="language-plaintext highlighter-rouge">sudo systemctl restart dovecot</code>. Kill me. I am <em>guessing</em> I had to restart the mail service because certificate has changed and it had to pick up the new one. I bet if I had run this command right after <code class="language-plaintext highlighter-rouge">certbot renew</code> I would not face any issues. The error messages caused by missing mx records were not related with this problem but I was confused by them and I thought something wrong with my certificates.</p>
</li>
</ul>
<p>Any way, I am happy that it is finally fixed. Did I learn something from this? Not much. But yeah, sometimes all you need is a simple restart :D</p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-04-13">April 13, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" class="pagination--pager" title="Never Get Trapped in Grub Rescue Again!
">Previous</a>
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" class="pagination--pager" title="Rant: Stop whatever you are doing and learn how licenses work
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" rel="permalink">Never Get Trapped in Grub Rescue Again!
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
4 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” m...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,645 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Rant: Stop whatever you are doing and learn how licenses work - Şahin Akkayas Personal Page</title>
<meta name="description" content="Recently, Github announced that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list. When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it: Pay the subscription fee and get it. Prove you are a student and get it for free. Be a maintainer of a popular repository and get it for free.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Rant: Stop whatever you are doing and learn how licenses work">
<meta property="og:url" content="https://sahinakkaya.dev/2022/06/22/rant-on-peoples-reaction-to-copilot.html">
<meta property="og:description" content="Recently, Github announced that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list. When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it: Pay the subscription fee and get it. Prove you are a student and get it for free. Be a maintainer of a popular repository and get it for free.">
<meta property="article:published_time" content="2022-06-22T07:46:00+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/06/22/rant-on-peoples-reaction-to-copilot.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Rant: Stop whatever you are doing and learn how licenses work">
<meta itemprop="description" content="Recently, Github announced that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list.When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it: Pay the subscription fee and get it. Prove you are a student and get it for free. Be a maintainer of a popular repository and get it for free.">
<meta itemprop="datePublished" content="2022-06-22T07:46:00+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Rant: Stop whatever you are doing and learn how licenses work
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<p>Recently, Github <a href="https://github.blog/changelog/2022-06-21-github-copilot-is-now-available-to-individual-developers/">announced</a>
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list.
When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it:</p>
<ul>
<li>Pay the subscription fee and get it.</li>
<li>Prove you are a student and get it for free.</li>
<li>Be a maintainer of <em>a popular repository</em> and get it for free.</li>
</ul>
<p>I think I should be able to use it for free because I am a student but apparently they are not convinced yet. Anyways, that is a different
story. I dont care if they will give me access to Github Copilot or not. It is not a big deal for me.</p>
<p>But some people were really angry about how Github Team being vague while defining the criteria as “being a maintainer of a popular open source project”.
I think they are right to some extent. If all you need is having a few thousands stars for a project, you could easily get that. I know a lot of troll
or low effort repositories that get a lot of stars because they are funny.</p>
<p>Later, I found <a href="https://twitter.com/fatih/status/1539574219629105156">another tweet</a> that explains how Github decides what is <em>popular</em>. According to
this tweet, if you have a repository that is in top 1000 in one of the most popular 34 languages, you are eligible to get Github Copilot for free.
This is better than the previous definition but you can still argue that it is not fair because one can create a package for checking if a number is
even or not and get thousands of stars.</p>
<p>You can criticize this, I get that. But do not come up with silly arguments to justify yourself. Like how on earth would you think that Github is doing
something bad because $10/month is too much for this service? It is business man, you pay if you think it is worth it. Thats it. <em>“I joined beta program
and it was free, now they want to charge me if I want to continue using it. They did not tell me that.”</em> Uhhm… What? Are you aware that what you are using
is another companys service and they have all rights to do whatever they want with their service? How you guys even can build up arguments like that?! This is crazy!</p>
<p>Some people argue that <em>“what Github is doing is wrong because they used open source projects <strong>without consent</strong>.”</em> Another similar argument is that <em>“what
Github is doing is evil because they used projects developed by community and now they are selling it without giving any money to the contributors of
these projects.”</em> Do you guys even have an idea what licenses stands for? If you dont want to some random person use your code, just license it that
way. And if you licensed it with a GPL compatible or similar license you already gave rights anyone to use or sell your code. That is not Githubs
problem. That is your problem not understanding how licenses work. Stop complaining.</p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/04/08/confession-time.html" class="pagination--pager" title="Confession Time
">Previous</a>
<a href="/2022/12/29/recap-of-2022.html" class="pagination--pager" title="Recap of 2022
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" rel="permalink">Never Get Trapped in Grub Rescue Again!
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
4 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” m...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,627 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Recap of 2022 - Şahin Akkayas Personal Page</title>
<meta name="description" content="Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Recap of 2022">
<meta property="og:url" content="https://sahinakkaya.dev/2022/12/29/recap-of-2022.html">
<meta property="og:description" content="Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.">
<meta property="article:published_time" content="2022-12-29T20:22:08+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2022/12/29/recap-of-2022.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Recap of 2022">
<meta itemprop="description" content="Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.">
<meta itemprop="datePublished" content="2022-12-29T20:22:08+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Recap of 2022
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<p>Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.</p>
<p>The biggest problem of my life is the graduation project. Oh, God it is making me sick! I simply dont have any interest for the subject I am supposed to work on. One part of me saying that “come on, you came this far. You are nearly finished. One last push!” and other part of me saying “oh no, dont do it. You have never done something you dont like in your entire life. F*ck it!”. So I am wasting my time each term with the dilemma I just described. I really dont know what to do. This thing is fed up.</p>
<p>Second biggest problem is I live in Turkey. I feel like all my friends somehow get rid of this sh*thole and I am locked here. I use Twitter and Reddit to consume daily news and almost everyday I encounter something that make me say “F*ck me, why I am still here? There is no hope”. Actually, the situation was much worse while I was following pages that shares “street interviews”. At first I started watching them <em>for fun</em> but the stupidity of people was real and harming my mental health. Since that day, I started consuming only news. My experience got better but I feel like it is still affecting me in a bad manner because everyday something bad happens and there is not much I can do to fix. Today, I decided to delete Twitter and Reddit. Ill see how it goes.</p>
<p>I am living with my parents for the past 6 months, I break up with my girlfriend, I left the place I was working. Man, this could be the worst year of my life!</p>
<p><img src="/assets/images/recap-2022/jackie-chan-wtf.jpg" alt="Jackie Chan WTF meme"></p>
<p>You know what? I am not gonna give up. <em>“… It aint about how hard you get hit. Its about how hard you get hit and keep moving forward. How much you can take, and keep moving forward…”</em> No, seriously things really will be different for me in 2023 I can feel it. I learn from my mistakes, they are making me even more perfect :D I love myself, I got this.</p>
<p><img src="/assets/images/recap-2022/i-got-this.jpg" alt='Disaster girl saying "I got this"'></p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time></p>
</footer>
<nav class="pagination">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" class="pagination--pager" title="Rant: Stop whatever you are doing and learn how licenses work
">Previous</a>
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" class="pagination--pager" title="Hot-Reload Long Running Shell Scripts (feat. trap / kill)
">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" rel="permalink">Never Get Trapped in Grub Rescue Again!
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
4 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” m...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -0,0 +1,840 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Hot-Reload Long Running Shell Scripts (feat. trap / kill) - Şahin Akkayas Personal Page</title>
<meta name="description" content="trap them and kill them! There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is also good ol kill command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!">
<meta name="author" content="Şahin Akkaya">
<meta property="article:author" content="Şahin Akkaya">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Hot-Reload Long Running Shell Scripts (feat. trap / kill)">
<meta property="og:url" content="https://sahinakkaya.dev/2023/01/15/hot-reloading-with-trap-and-kill.html">
<meta property="og:description" content="trap them and kill them! There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is also good ol kill command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!">
<meta property="article:published_time" content="2023-01-15T21:48:08+00:00">
<link rel="canonical" href="https://sahinakkaya.dev/2023/01/15/hot-reloading-with-trap-and-kill.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Hot-Reload Long Running Shell Scripts (feat. trap / kill)">
<meta itemprop="description" content="trap them and kill them!There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is also good ol kill command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!">
<meta itemprop="datePublished" content="2023-01-15T21:48:08+00:00">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</h1>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
</header>
<section class="page__content" itemprop="text">
<h2 id="trap-them-and-kill-them">
<code class="language-plaintext highlighter-rouge">trap</code> them and <code class="language-plaintext highlighter-rouge">kill</code> them!</h2>
<p>There is a beautiful command in Linux called <a href="https://man7.org/linux/man-pages/man1/trap.1p.html"><code class="language-plaintext highlighter-rouge">trap</code></a> which <em>trap</em>s signals and let you run specific commands when they invoked. There is also good ol <a href="https://man7.org/linux/man-pages/man1/kill.1.html"><code class="language-plaintext highlighter-rouge">kill</code></a> command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!</p>
<h3 id="basic-example">Basic Example</h3>
<p>Lets start by creating something very simple and build up from there. Create a script with the following contents:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="nb">echo</span> <span class="s2">"My pid is </span><span class="nv">$$</span><span class="s2">. Send me SIGUSR1!"</span>
func<span class="o">()</span> <span class="o">{</span>
<span class="nb">echo</span> <span class="s2">"Got SIGUSR1"</span>
<span class="o">}</span>
<span class="c"># here we are telling that run 'func' when USR1 signal is</span>
<span class="c"># received. You can run anything. Combine commands with ; etc.</span>
<span class="nb">trap</span> <span class="s2">"func"</span> USR1
<span class="c"># The while loop is important here otherwise our script will exit</span>
<span class="c"># before we manage to get a chance to send a signal.</span>
<span class="k">while </span><span class="nb">true</span> <span class="p">;</span> <span class="k">do
</span><span class="nb">echo</span> <span class="s2">"waiting SIGUSR1"</span>
<span class="nb">sleep </span>1
<span class="k">done</span>
</code></pre></div></div>
<p>Now make it executable and run it:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">chmod</span> +x trap_example
./trap_example
My pid is 2811137. Send me SIGUSR1!
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
</code></pre></div></div>
<p>Open another terminal and send your signal with <code class="language-plaintext highlighter-rouge">kill</code> to the specified pid.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">kill</span> <span class="nt">-s</span> USR1 2811137
</code></pre></div></div>
<p>You should receive <code class="language-plaintext highlighter-rouge">"Got SIGUSR!"</code> from the other process. Thats it! Now, imagine you write whatever thing you want to execute in <code class="language-plaintext highlighter-rouge">func</code> and then you can simply <code class="language-plaintext highlighter-rouge">kill -s ...</code> anytime and as many times you want!</p>
<p>Lets move the while loop into the <code class="language-plaintext highlighter-rouge">func</code> and add some variables so you can see how powerful this is.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="nb">echo</span> <span class="s2">"My pid is </span><span class="nv">$$</span><span class="s2">. Send me SIGUSR1!"</span>
func<span class="o">()</span> <span class="o">{</span>
<span class="nv">i</span><span class="o">=</span>1
<span class="k">while </span><span class="nb">true</span> <span class="p">;</span> <span class="k">do
</span><span class="nb">echo</span> <span class="s2">"i: </span><span class="nv">$i</span><span class="s2">"</span>
<span class="nv">i</span><span class="o">=</span><span class="k">$((</span> i <span class="o">+</span> <span class="m">1</span> <span class="k">))</span>
<span class="nb">sleep </span>1
<span class="k">done</span>
<span class="o">}</span>
<span class="nb">trap</span> <span class="s2">"echo 'Got SIGUSR1!'; func"</span> USR1
<span class="c"># we need to call the function once, otherwise script</span>
<span class="c"># will exit before we manage to send a signal</span>
func
</code></pre></div></div>
<p>Now run the script and send <code class="language-plaintext highlighter-rouge">SIGUSR1</code>. Here is the result:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ./trap_example
My pid is 2880704. Send me SIGUSR1!
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
Got SIGUSR1!
i: 1
i: 2
i: 3
i: 4
i: 5
Got SIGUSR1!
i: 1
i: 2
^C
</code></pre></div></div>
<p>Isnt this neat?</p>
<h3 id="more-useful-example">More useful example</h3>
<p>Lets imagine you have multiple long running (infinite loops basically) scripts and you want to restart them without manually searching for their pids and killing them. <code class="language-plaintext highlighter-rouge">trap</code> is for the rescue, again! <sup><a href="##" title="Yeah, I know you can run a systemd service if you want but I think it is an overkill for this situation. Plus, I don't like dealing with them.">*</a></sup> This command is awesome.</p>
<p>Without further ado, lets get started. Create a script called <code class="language-plaintext highlighter-rouge">script1</code> with the following contents:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="c"># file: script1</span>
<span class="nv">i</span><span class="o">=</span>1
<span class="k">while </span><span class="nb">true</span> <span class="p">;</span> <span class="k">do
</span><span class="nb">echo</span> <span class="s2">"Hello from </span><span class="nv">$0</span><span class="s2">. i is </span><span class="nv">$i</span><span class="s2">"</span>
<span class="nv">i</span><span class="o">=</span><span class="k">$((</span> i <span class="o">+</span> <span class="m">1</span> <span class="k">))</span>
<span class="nb">sleep </span>1
<span class="k">done</span>
</code></pre></div></div>
<p>And symlink it to another name just for fun:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">chmod</span> +x script1
<span class="nb">ln</span> <span class="nt">-s</span> script1 script2
</code></pre></div></div>
<p>Now we can pretend they are two different scripts as their outputs differ:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ./script1
Hello from ./script1. i is 1
Hello from ./script1. i is 2
Hello from ./script1. i is 3
Hello from ./script1. i is 4
^C
./script2
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script2. i is 3
^C
</code></pre></div></div>
<p>Finally, create the main script which will start child scripts and restart them on our signals:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="nb">echo</span> <span class="s2">"My pid is </span><span class="nv">$$</span><span class="s2">. You know what to do ( ͡° ͜ʖ ͡°)"</span>
<span class="nb">echo</span> <span class="s2">"You can also kill me with 'kill -s INT -</span><span class="se">\`</span><span class="s2">pgrep -f </span><span class="sb">`</span><span class="nb">basename</span> <span class="nv">$0</span><span class="sb">`</span><span class="se">\`</span><span class="s2">'"</span>
<span class="nv">pids</span><span class="o">=()</span> <span class="c"># we will store the pid's of child scripts here</span>
<span class="nv">scripts_to_be_executed</span><span class="o">=(</span><span class="s2">"./script1"</span> <span class="s2">"./script2"</span><span class="o">)</span>
kill_childs<span class="o">(){</span> <span class="c"># wow, this sounded wild</span>
<span class="k">for </span>pid <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">pids</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
<span class="k">do
</span><span class="nb">echo </span>killing <span class="s2">"</span><span class="nv">$pid</span><span class="s2">"</span>
<span class="c"># -P: kill all the processes whose parent process is 'pid'</span>
<span class="c"># see how we are creating processes below</span>
pkill <span class="nt">-P</span> <span class="s2">"</span><span class="nv">$pid</span><span class="s2">"</span>
<span class="k">done
</span><span class="nv">pids</span><span class="o">=()</span>
<span class="o">}</span>
<span class="c"># kill childs and restart all the scripts</span>
restart_scripts<span class="o">(){</span>
kill_childs
<span class="c"># for each script in the list</span>
<span class="k">for </span>script <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">scripts_to_be_executed</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
<span class="k">do</span>
<span class="c"># Run the script and store its pid.</span>
<span class="c"># note the '&amp;' at the end of command. Without it the script will</span>
<span class="c"># block until its execution is finished. Also we are putting it</span>
<span class="c"># into braces because we want to create a "process group" so that</span>
<span class="c"># we can kill all its children later by specifying parent pid</span>
<span class="c"># (useful if you have pipes (|) or other &amp;'s in your script!)</span>
<span class="o">(</span><span class="nv">$script</span><span class="o">)</span> &amp;
pids+<span class="o">=(</span><span class="s2">"</span><span class="nv">$!</span><span class="s2">"</span><span class="o">)</span>
<span class="k">done</span>
<span class="o">}</span>
<span class="c"># we will restart_scripts with SIGUSR1 signal</span>
<span class="nb">trap</span> <span class="s1">'echo "restarting scripts"; restart_scripts'</span> USR1
<span class="c"># we will kill all the childs and exit the main script with SIGINT</span>
<span class="c"># which is same signal as when you press &lt;Control-C&gt; on your terminal</span>
<span class="nb">trap</span> <span class="s1">'echo exiting; kill_childs; exit'</span> INT
<span class="c"># run the function once</span>
restart_scripts
<span class="c"># infinite loop, otherwise main script will exit before we send signal.</span>
<span class="c"># remember, we started child processes with '&amp;' so they won't block this script</span>
<span class="k">while </span><span class="nb">true</span><span class="p">;</span> <span class="k">do
</span><span class="nb">sleep </span>1
<span class="k">done</span>
</code></pre></div></div>
<p>Now, you can run your main script and reload your child scripts any time with <code class="language-plaintext highlighter-rouge">killall main_script -USR1</code></p>
<p>Here is an example run:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ./trap_multiple
My pid is 3124123. You know what to do ( ͡° ͜ʖ ͡°)
You can also kill me with 'kill -s INT -`pgrep -f trap_multiple`'
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script1. i is 2
Hello from ./script2. i is 3
Hello from ./script1. i is 3
restarting scripts
killing 3124125
killing 3124126
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script1. i is 2
Hello from ./script2. i is 3
Hello from ./script1. i is 3
Hello from ./script2. i is 4
Hello from ./script1. i is 4
restarting scripts
killing 3124304
killing 3124305
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script1. i is 2
Hello from ./script2. i is 2
^Cexiting
killing 3124875
killing 3124876
</code></pre></div></div>
<h3 id="final-words">Final words</h3>
<p>I think I am started to getting obsessed with <code class="language-plaintext highlighter-rouge">trap</code> command because it has such a good name and purpose. FOSS people are really on another level when it comes to naming. Here is another good one:</p>
<blockquote>
<p>- How can you see the contents of a file? <br>
+ You <em><code class="language-plaintext highlighter-rouge">cat</code></em> it. <br>
- What if you want to see them in reverse order? <br>
+ You <em><code class="language-plaintext highlighter-rouge">tac</code></em> it. <br></p>
</blockquote>
<p>No, it is not just a joke. Try it… Man I love Gnoo slash Linux.</p>
<p>Anyway, I hope now you know how to <code class="language-plaintext highlighter-rouge">trap</code> and <code class="language-plaintext highlighter-rouge">kill</code>. Next week I will explain how to <code class="language-plaintext highlighter-rouge">unzip; strip; touch; finger; grep; mount; fsck; more; yes; fsck; fsck; umount; clean; sleep</code> <nobr>( ͡° ͜ʖ ͡°)</nobr>. <sup><a href="##" title="jk :D">*</a></sup></p>
</section>
<footer class="page__meta">
<p class="page__date"><strong><i class="fas fa-fw fa-calendar-alt" aria-hidden="true"></i> Updated:</strong> <time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time></p>
</footer>
<nav class="pagination">
<a href="/2022/12/29/recap-of-2022.html" class="pagination--pager" title="Recap of 2022
">Previous</a>
<a href="#" class="pagination--pager disabled">Next</a>
</nav>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" rel="permalink">Never Get Trapped in Grub Rescue Again!
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-fw fa-clock" aria-hidden="true"></i>
4 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” m...</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

209
404.html
View File

@ -1,9 +1,147 @@
---
permalink: /404.html
layout: default
---
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<style type="text/css" media="screen">
<!-- begin _includes/seo.html --><title>Şahin Akkaya's Personal Page</title>
<meta name="description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<meta name="author" content="Şahin Akkaya">
<meta property="og:type" content="website">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Şahin Akkayas Personal Page">
<meta property="og:url" content="https://sahinakkaya.dev/404.html">
<meta property="og:description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<link rel="canonical" href="https://sahinakkaya.dev/404.html">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--default">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
@ -23,3 +161,64 @@ layout: default
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

36
Gemfile
View File

@ -1,36 +0,0 @@
source 'https://rubygems.org'
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem 'jekyll', '~> 4.2.1'
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem 'minima', '~> 2.5'
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
gem 'jekyll-include-cache'
gem 'minimal-mistakes-jekyll'
gem 'jekyll-spaceship'
group :jekyll_plugins do
gem 'jekyll-feed', '~> 0.12'
end
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem 'tzinfo', '~> 1.2'
gem 'tzinfo-data'
end
# Performance-booster for watching directories on Windows
gem 'wdm', '~> 0.1.1', platforms: %i[mingw x64_mingw mswin]
gem "webrick", "~> 1.7"

View File

@ -1,136 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
colorator (1.1.0)
concurrent-ruby (1.1.9)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
eventmachine (1.2.7)
faraday (1.8.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
ffi (1.15.4)
forwardable-extended (2.6.0)
gemoji (3.0.1)
http_parser.rb (0.8.0)
i18n (1.8.11)
concurrent-ruby (~> 1.0)
jekyll (4.2.1)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (~> 2.0)
jekyll-watch (~> 2.0)
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (~> 0.4.0)
pathutil (~> 0.9)
rouge (~> 3.0)
safe_yaml (~> 1.0)
terminal-table (~> 2.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-paginate (1.1.0)
jekyll-sass-converter (2.1.0)
sassc (> 2.0.1, < 3.0)
jekyll-seo-tag (2.7.1)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-spaceship (0.10.2)
gemoji (~> 3.0)
jekyll (>= 3.6, < 5.0)
nokogiri (~> 1.6)
rainbow (~> 3.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.7.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minimal-mistakes-jekyll (4.24.0)
jekyll (>= 3.7, < 5.0)
jekyll-feed (~> 0.1)
jekyll-gist (~> 1.5)
jekyll-include-cache (~> 0.1)
jekyll-paginate (~> 1.1)
jekyll-sitemap (~> 1.3)
multipart-post (2.1.1)
nokogiri (1.14.0-x86_64-linux)
racc (~> 1.4)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.6)
racc (1.6.2)
rainbow (3.1.1)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.27.0)
ruby2_keywords (0.0.5)
safe_yaml (1.0.5)
sassc (2.4.0)
ffi (~> 1.9)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
terminal-table (2.0.0)
unicode-display_width (~> 1.1, >= 1.1.1)
unicode-display_width (1.8.0)
webrick (1.7.0)
PLATFORMS
x86_64-linux
DEPENDENCIES
jekyll (~> 4.2.1)
jekyll-feed (~> 0.12)
jekyll-include-cache
jekyll-spaceship
minima (~> 2.5)
minimal-mistakes-jekyll
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.1)
webrick (~> 1.7)
BUNDLED WITH
2.3.1

View File

@ -1,111 +0,0 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
#
# If you need help with YAML syntax, here are some quick references for you:
# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
# https://learnxinyminutes.com/docs/yaml/
#
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Şahin Akkaya's Personal Page
email: sahin@sahinakkaya.dev
description: >- # this means to ignore newlines until "baseurl:"
Şahin Akkaya's personal blog - a perfectionist who likes to tinker everything
until it is just right. Get ready to find some sweet tips that will boost your
productivity and make you fall in love with your computer.
baseurl: "" # the subpath of your site, e.g. /blog
url: "https://sahinakkaya.dev" # the base hostname & protocol for your site, e.g. http://example.com
twitter_username: sahinakkayadev
github_username: sahinakkaya
search: true
search_full_content: true
lunr:
search_within_pages: true
defaults:
# _posts
- scope:
path: ""
type: posts
values:
layout: single
author_profile: true
read_time: true
show_date: true
comments: true
share: false
related: true
# _pages
- scope:
path: ""
type: pages
values:
layout: single
author_profile: true
author:
name : "Şahin Akkaya"
avatar : "/assets/images/logo.jpg"
bio : "A perfectionist who likes to tinker everything until it is just right."
location : "Istanbul, Turkey"
links:
- label: "sahinakkaya"
icon: "fab fa-fw fa-github"
url: "https://github.com/sahinakkaya"
- label: "Asocia"
icon: "fab fa-fw fa-stack-overflow"
url: "https://stackoverflow.com/users/9608759"
- label: "@sahinakkayadev"
icon: "fab fa-fw fa-twitter-square"
url: "https://twitter.com/sahinakkayadev"
- label: "sahin@sahinakkaya.dev"
icon: "fas fa-fw fa-envelope"
url: "mailto:sahin@sahinakkaya.dev"
- label: "Resume"
icon: "fas fa-fw fa-id-card"
url: "/assets/docs/resume.pdf"
masthead_title: "/home/sahin/"
keep_files: [.git]
# Build settings
theme: minimal-mistakes-jekyll
minimal_mistakes_skin: "neon" # "air", "aqua", "contrast", "dark", "dirt", "neon", "mint", "plum" "sunrise"
plugins:
- jekyll-feed
- jekyll-include-cache
- jekyll-spaceship
# Exclude from processing.
# The following items will not be processed, by default.
# Any item listed under the `exclude:` key here will be automatically added to
# the internal "default list".
#
# Excluded items can be processed by explicitly listing the directories or
# their entries' file path in the `include:` list.
#
# exclude:
# - .sass-cache/
# - .jekyll-cache/
# - gemfiles/
# - Gemfile
# - Gemfile.lock
# - node_modules/
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/

View File

@ -1,7 +0,0 @@
main:
- title: "Home"
url: /
- title: "About"
url: /about/
- title: "Contact"
url: /contact/

View File

@ -1,24 +0,0 @@
<div class="page__footer-follow">
<ul class="social-icons">
{% if site.data.ui-text[site.locale].follow_label %}
<li><strong>{{ site.data.ui-text[site.locale].follow_label }}</strong></li>
{% endif %}
{% if site.footer.links %}
{% for link in site.footer.links %}
{% if link.label and link.url %}
<li><a href="{{ link.url }}" rel="nofollow noopener noreferrer"><i class="{{ link.icon | default: 'fas fa-link' }}" aria-hidden="true"></i> {{ link.label }}</a></li>
{% endif %}
{% endfor %}
{% endif %}
{% unless site.atom_feed.hide %}
<li><a href="{% if site.atom_feed.path %}{{ site.atom_feed.path }}{% else %}{{ '/feed.xml' | relative_url }}{% endif %}"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> {{ site.data.ui-text[site.locale].feed_label | default: "Feed" }}</a></li>
{% endunless %}
</ul>
</div>
<div class="page__footer-copyright">&copy; {{ site.time | date: '%Y' }} {{ site.name | default: site.title }}. {{ site.data.ui-text[site.locale].powered_by | default: "Powered by" }} <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://git.sahinakkaya.dev/sahin/sahinakkaya.dev">code</a> of this site.
</div>

View File

@ -1,39 +0,0 @@
---
title: "First blog post"
date: 2021-12-25 02:54:08 +0300
excerpt: Hello, World!* So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it fi...
---
<style>
.ab {
font-size: 1.3em;
line-height:0;
top:0;
}
.cd {
text-decoration: none;
}
</style>
*`Hello, World!`*[<sup class="ab">*</sup>](## "I think I just wrote the best first sentence I could write as a programmer :D"){: .cd}
So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it finally have come true. You might think that I could sign-up for a social media platform and my profile would be a personal space for me but no. I just don't feel comfortable with that way. This has been the case since my childhood and also the reason why I don't use Facebook, Instagram or any other social media. If you think you found me on these platforms, I would say it is not me. I might write another post about why I don't like social media but I will cut this one here.
## Why I wanted to start blogging?
There are several reasons for starting my own site and blogging, but I can list the most important ones as follows:
### Giving back to community
I use the software developed and brought by the community every day. The moment I power on my computer I start using Free Software. It really amazes me to see the work produced by people who do not know each other at all. For example, I did not even write a single line of code for this site. If Free Software didn't exist, I'd either have to spend money and use a platform that I have limited control over, or waste my time and build a site with a possibly worse design than this one[<sup class="ab">*</sup>](## "swh"){: .cd}. In return for this, I want to give back to the community. For me, the way to give back to the community so far has been to share the projects I've done and archive the things I learn every day in a repository called [TIL](https://github.com/sahinakkaya/til)[<sup class="ab">*</sup>](## "Today I Learned"){: .cd}. But some of the til's I've written recently are getting lengthy and I think they deserve their own posts. So instead of writing long til's, I will blog what I learned here.
### Archiving the memories
I like to go over what I have done in the past once in a while. Blogging is perfect way to do this. I still read my diaries that I wrote in the past and they are fun. But I promise I will keep these posts more formal than my diaries[<sup class="ab">*</sup>](## "swh"){: .cd}.
### Pushing myself to do something useful
At the end of every year, I sit on my desk and think about what I did in that year. I generally don't like the result because I fail to keep some of my resolutions for that year. Setting up a personal website was one of my resolutions for 2021 and it looks like I manage to keep it[<sup class="ab">*</sup>](## "hooray!"){: .cd}[<sup class="ab">*</sup>](## "swh"){: .cd}. Unfortunately, I can't always keep my spirits up. Sometimes I just do nothing and all the time passes. Hopefully, the feeling that I have to write something will help me get out of bad mood at such times.
### Improving my writing skills
Last but not least, I want to improve my writing. Even though I don't use a formal language while writing here, I think it will help me improve my writing skills.
## Final words
While writing this post I already come up with some new topics to write but I think they need their own posts.
Subscribe to my <a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i>RSS Feed</a> to not miss them. You know RSS, right? I recently started using it and it is the best way to consume content. Do yourself a favor and search it if you don't know. I will probably write something about it in the following blog posts. That's all from me and thank you for reading. See you next time!

View File

@ -1,65 +0,0 @@
---
title: "Stop cat-pipe'ing, You Are Doing It Wrong!"
date: 2022-01-01 18:00:00 +0300
tags: cat grep linux command-line
---
```bash
cat some_file | grep some_pattern
```
I'm sure that you run a command something like above at least once if you are using terminal. You know how `cat` and `grep` works and you also know what pipe (`|`) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didn't know is that `grep` already accepts file as an argument. So the above command could be rewritten as:
```bash
grep some_pattern some_file
```
... which can make you save a few keystrokes and a few nanoseconds of CPU cycles. Phew! Not a big deal if you are not working files that contains GBs of data, right? I agree but you should still use the latter command because it will help you solve some other problems better. Here is a real life scenario: You want to search for some specific pattern in all the files in a directory.
- If you use the first approach, you may end up running commands like this:
```bash
ls
 config.lua  Git.lua  init.lua  markdown.lua  palette.lua  util.lua
 diff.lua  highlights.lua  LSP.lua  Notify.lua  Treesitter.lua  Whichkey.lua
cat config.lua | grep light
cat diff.lua | grep light
cat Git.lua | grep light
cat highlights.lua | grep light
Pmenu = { fg = C.light_gray, bg = C.popup_back },
CursorLineNr = { fg = C.light_gray, style = "bold" },
Search = { fg = C.light_gray, bg = C.search_blue },
IncSearch = { fg = C.light_gray, bg = C.search_blue },
cat init.lua | grep light
local highlights = require "onedarker.highlights"
highlights,
# You still have a lot to do :/
```
- If you use the second approach, you will immediately realize that you can send all the files with `*` operator and you will finish the job with just one command (2 if you include mandatory `ls` :D):
```bash
ls
 config.lua  Git.lua  init.lua  markdown.lua  palette.lua  util.lua
 diff.lua  highlights.lua  LSP.lua  Notify.lua  Treesitter.lua  Whichkey.lua
grep light *
highlights.lua: Pmenu = { fg = C.light_gray, bg = C.popup_back },
highlights.lua: CursorLineNr = { fg = C.light_gray, style = "bold" },
highlights.lua: Search = { fg = C.light_gray, bg = C.search_blue },
highlights.lua: IncSearch = { fg = C.light_gray, bg = C.search_blue },
init.lua:local highlights = require "onedarker.highlights"
init.lua: highlights,
LSP.lua: NvimTreeNormal = { fg = C.light_gray, bg = C.alt_bg },
LSP.lua: LirFloatNormal = { fg = C.light_gray, bg = C.alt_bg },
markdown.lua: markdownIdDelimiter = { fg = C.light_gray },
markdown.lua: markdownLinkDelimiter = { fg = C.light_gray },
palette.lua: light_gray = "#abb2bf",
palette.lua: light_red = "#be5046",
util.lua:local function highlight(group, properties)
util.lua: "highlight",
util.lua: highlight(group, properties)
```
Isn't this neat? You might say that *"This is cheating! You are using a wild card, of course it will be easier."* Well, yes. Technically I could use the same wild card in the first command like `cat * | grep light` but:
- I figured that out only after using wild card in the second command. So I think it is does not feel natural.
- It is still not giving the same output. Try and see the difference! [*](## "You will not be able to see which file contains which line. 'cat' will just concatenate all the input.")

View File

@ -1,198 +0,0 @@
---
title: "Automatically Build and Deploy Your Site using GitHub Actions and Webhooks"
date: 2022-01-04 20:40:00 +0300
tags: github-actions github-webhooks ci-cd
---
In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.
## Introduction to GitHub Actions and Webhooks
Let me start by explaining what are GitHub Actions and GitHub Webhooks.
> **Github Actions** is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.
> **Webhooks** provide a way for notifications to be delivered to an external web server whenever certain actions occur on a repository or organization. ... For example, you can configure a webhook to execute whenever:
- A repository is pushed to
- A pull request is opened
- A GitHub Pages site is built
- A new member is added to a team
## Defining the problem and solution
As I said, my example will be automating the deployment of this site. Here is the normal workflow of me doing it manually:
![My workflow](/assets/images/gh-actions-and-webhooks/workflow.png)
As you can see, the only place where my work is really required is writing the post. Other two steps can be automated. We will use GitHub Actions to generate the site content and Webhooks to let our server know about the new content so it can pull the changes. Let's get started.
### Setting up GitHub Actions
Setting up a GitHub Action is as easy as creating a `.yml` file in `.github/workflows/` directory in your repository. Let us create a new action to build our site. Fortunately, there is already a [GitHub action](https://github.com/marketplace/actions/jekyll-actions) to do it for us. Create a file called `.github/workflows/jekyll.yml` in your root directory of your repository and put the following contents:
```yaml
name: Jekyll site CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Jekyll Actions
uses: helaili/jekyll-action@2.2.0
with:
{% raw %}token: ${{ secrets.GITHUB_TOKEN }} {% endraw %}
keep_history: true
target_branch: 'gh-pages'
```
That's it! We have created our first Action. When we push this change, GitHub will start building our site and push the result to `gh-pages` branch. Currently, it will take a while to build because we don't use caching. So let's include it to build faster. Add the following piece as a second step:
```yaml
# Use GitHub Actions' cache to shorten build times and decrease load on servers
- uses: actions/cache@v2
with:
path: vendor/bundle
{% raw %}key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile') }}
restore-keys: |
${{ runner.os }}-gems-{% endraw %}
```
We are done with the Actions part. You can see the final code [here](https://github.com/sahinakkaya/sahinakkayadotdev/blob/main/.github/workflows/jekyll.yml). When you are also done with the code, just push it to trigger the action.
### Setting up the Webhook and related endpoint
Now that we set up our Action to build the site, we need to let our server know about the changes so that it can pull the changes.
#### Creating a Webhook from GitHub
To add a Webhook, open your repository in browser and navigate to *'Settings > Webhooks'* and click *'Add Webhook'*. Fill in the form with appropriate values. Here is an example:
![Webhook form example](/assets/images/gh-actions-and-webhooks/add-webhook.png)
This is all you have to do from GitHub. Now, whenever there is a *`push`* event to your repository, GitHub will send a POST request to your *payload url* with the details.
**Note:** Our Action is configured to push to a branch in our repository, so it will also trigger this hook and we will catch it.
{: .notice--info}
#### Creating an endpoint to handle the requests
I will use [Flask](https://flask.palletsprojects.com/en/2.0.x/) framework to handle the post requests coming to our endpoint. You can use whatever programming language or framework you want. It will be very simple code with just one job: Validate the secret keys and run a specific code.
Let's start by creating a new project and a virtual environment:
```bash
mdkir post_receiver
cd post_receiver
python3 -m venv venv
source venv/bin/activate
```
Install the required packages:
```bash
pip install Flask gunicorn
```
Create a new file for storing our environment variables:
```python
# config.py
APP_KEY = "your-secret-key" # same key that is used in github while creating the webhook
PROJECT_PATH = "/path/to/your/project/" # you will want to cd into this path and perform commands such as git pull etc.
```
And create the Flask application:
```python
# post_receiver.py
import hashlib
import hmac
import subprocess
from flask import Flask, request
import config
application = Flask(__name__)
@application.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'GET':
return 'OK'
elif request.method == 'POST':
content = request.data
secret = bytes(config.APP_KEY, 'utf-8')
digester = hmac.new(secret, content, hashlib.sha256)
calculated_signature = 'sha256=' + digester.hexdigest()
actual_signature = request.headers.get('X-Hub-Signature-256')
if calculated_signature == actual_signature:
subprocess.Popen(
['./perform-git-pull.sh', config.PROJECT_PATH])
return 'OK'
else:
return 'Error'
if __name__ == "__main__":
application.run(host='0.0.0.0')
```
I will not go into details explaining what each line does. Basically, we are checking if the request is a POST request and if so we are comparing the secret keys to make sure that the request is coming from GitHub. In our case, this is not too important because when the keys match we are running simple git commands in our repository but you might need it if you are doing something more complicated. And here is the contents of `perform-git-pull.sh` file:
```bash
#!/bin/bash
cd $1
git checkout gh-pages
git pull
```
We are almost done! All we need to do is create a service to automatically run our code and let nginx handle our endpoint correctly.
Create a new file `post_receiver.service` in `/etc/systemd/system/`:
```
#/etc/systemd/system/post_receiver.service
# change <user> to your actual username
[Unit]
Description=post_receiver
After=network.target multi-user.target
[Service]
User=<user>
Environment="PYTHONPATH=/home/<user>/post_receiver/venv/bin/python"
WorkingDirectory=/home/<user>/post_receiver
ExecStart=/home/<user>/post_receiver/venv/bin/gunicorn -b 127.0.0.1:5000 -w 2 --log-file /home/<user>/post_receiver/post_receiver.log post_receiver
[Install]
WantedBy=multi-user.target
```
Make sure port `5000` is reachable from outside.
```bash
sudo ufw allow 5000
sudo ufw enable
```
Finally, edit your nginx configuration, `/etc/nginx/sites-available/yoursite`
```
location = /postreceive/ {
proxy_pass http://localhost:5000/;
}
```
Start, restart the services
```bash
sudo systemctl daemon-reload
sudo systemctl start post_receiver
sudo systemctl enable post_receiver
sudo systemctl restart nginx
```
That's it! `curl https://yourdomain.com/postreceive/` should return `"OK"` and we are ready to accept POST requests from GitHub.
### Notes for debugging
In case anything goes wrong, here are a few tips to debug:
- Every GitHub Action produces a log that you can examine. Check them to see if anything is odd.
- In the *Webhooks* tab, there is a sub-tab called *Recent Deliveries*. You can take a look at there to see the results of the requests from your hooks.
- You can always test your code locally with `curl`:
```
curl -i -X POST -H 'Content-Type: application/json' -d '{"foo": "bar", "bar": "baz"}' https://yourdomain.com/postreceive/
```
Happy hacking!

View File

@ -1,32 +0,0 @@
---
title: "Using ffmpeg for Simple Video Editing"
date: 2022-01-21 23:40:00 +0300
tags: cli ffmpeg
excerpt:
---
## Story
Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up [Kdenlive](https://kdenlive.org/en/) and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give `ffmpeg` a shot.
## Let the show begin
Like Kdenlive, I have never used `ffmpeg` before. Like every normal Linux user do, I opened up a terminal and typed `man ffmpeg` to learn how to use it... Just kidding :D I opened a browser and typed *"ffmpeg cut video by time"*. Not the best search query, but it was good enough to find what I am looking for as the [first result](https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg).
### Cutting the videos based on start and end time
According to answers on the page I mentioned, I run the following commands to cut my video into two parts:
```bash
ffmpeg -ss 00:00:00 -to 00:01:55 -i input.mov -c copy part1.mp4 # take from 00:00 to 01:55
ffmpeg -ss 00:02:03 -to 00:05:17 -i input.mov -c copy part2.mp4 # take from 02:03 to 05:17
```
These two commands run **instantly**! Kdenlive was still rendering... The progress was 46%. Meh... I said "Duck it, I am gonna use ffmpeg only" and cancelled the rendering.
### Concatenating the video files
Now we have two videos that we want to join. Guess what will be our next search query? *"ffmpeg join videos"*. And [here](https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg) is the first result:
```bash
echo file part1.mp4 >> mylist.txt
echo file part2.mp4 >> mylist.txt
ffmpeg -f concat -i mylist.txt -c copy result.mp4
```
And we are DONE! How easy was that? Whole process took about 10 minutes including my search on the internet. If I continued waiting for Kdenlive to finish rendering, I would probably be still waiting at that time. I love the power of command line!

View File

@ -1,35 +0,0 @@
---
title: "Creating a *Useless* User"
date: 2022-02-27 16:40:00 +0300
tags: linux permissions privileges
---
## Story
In my [previous post]({% post_url 2022-02-27-ssh-into-machine-that-is-behind-private-network %}), I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriend's computer. Now, of course I don't want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.
## The solution
I searched the problem in it turned out to be very simple. You just need to add two additional flags to `adduser` command while creating the user.
```bash
sudo adduser uselessuser --shell=/bin/false --no-create-home
```
Now, `uselessuser` can't do anything useful in your server. If they try to login, the connection will be closed immediately.
```bash
ssh uselessuser@remote.host
uselessuser@remote.host\'s password:
Could not chdir to home directory /home/uselessuser: No such file or directory
Connection to remote.host closed.
```
But they can still do forward the remote port to their local machine.
```bash
ssh -Nf -R 7777:localhost:22 uselessuser@remote.host
uselessuser@remote.host\'s password:
```
The `-N` option is the most important one here. From the documentation:
> -N Do not execute a remote command. This is useful
for just forwarding ports. Refer to the description
of SessionType in ssh_config(5) for details.
## Last words
I love learning new things everyday. I knew setting the shell of a user to `/bin/false` will prevent them from logging in. The reason I wrote this blog post is because 2 things I wanted to share:
- While looking for a solution to the problem I mentioned, I searched *"create a user with no privileges in linux"* and [this](https://askubuntu.com/questions/1174376/how-to-create-a-user-with-the-least-privileges-permissions-but-enough-to-do-ssh) came out. It is really interesting for me that another person wanted to do the same thing for the *exact same reasons*. They were also trying port forwarding via ssh and they wanted to create a limited user in their server to give friends. So the question was a **perfect fit** to the problem.
- The `-N` flag of the ssh command was also surprising for me. It was like as if someone had encountered these problems before and just took the exact steps required to solve this problem for me. I mean look at the documentation. Crazy!

View File

@ -1,44 +0,0 @@
---
title: "SSH into Machine That Is Behind a Private Network"
date: 2022-02-27 00:40:00 +0300
tags: ssh private-network remote-port-forwarding
---
## Story
I believe there is always a "tech support person" in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.
## Possible solutions
- Just tell the non-tech people at home to configure the router to forward ssh traffic to desktop, right? Well, this is not an option for me, not because people are non-tech, but there is no router! The desktop is connected to internet via hotspot from mobile phone. There is no root access in the phone and even if there was, it is a really big pain to forward the packets manually. Trust me. Been there, done that!
- There are tools like [ngrok](https://www.ngrok.com), [localtunnel](localtunnel.me) which exposes your localhost to the internet and gives you a URL to access it but I did not want to use them.
- I did not want to use `ngrok` because it is not open source and it might have security issues. They are also charging you.
- `localtunnel` seemed perfect. The code of both client and server is open. That is great news! But it did not last long because it is just forwarding http/https traffic :(
## Solution
I was thinking of extending the functionality of `localtunnel`, but I learned a very simple way. You don't need any external program to overcome this issue. The good old `ssh` can do that! All you need is another machine (a remote server) that both computers can access via ssh.
```bash
# local machine (my home computer)
ssh -R 7777:localhost:22 remote-user@remote.host
```
This command forwards all the incoming connections to port 7777 of remote machine to port 22 of our current machine. In order for this to work, you need to make sure `GatewayPorts` is set to `yes` in the remote server ssh configuration. It also assumes our current machine accepts ssh connections via port 22.
---
Now, go to any machine and connect to the remote server first. When we are connected, we will create another ssh connection to port 7777 to connect our home computer.
```bash
# another local machine (my laptop)
ssh remote-user@remote.host
# connected remote
ssh -p 7777 homeuser@localhost
# we are now connected to home computer
```
The last two command can also combined so that we directly hop into the home computer.
```bash
ssh -t remote-user@remote.host ssh -p 7777 homeuser@localhost
```
### Result
As a result, it only took us 2 simple ssh commands to do this. This is just unbelievable! Now, I need to find a way to make non-tech people at home run this command when there is a problem. Too bad Linux can't help me there :D

View File

@ -1,68 +0,0 @@
---
title: "Never Get Trapped in Grub Rescue Again!"
date: 2022-03-03 03:46:00 +0300
tags: linux grub partition uefi
---
Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the "Grub rescue" menu and I don't know how to fix things from that point.
I go into the live environment and run some random commands that I found on the internet and hope for the best.
![me trying to fix grub](/assets/images/grub-rescue/random-bullshit.jpg)
What a nice way to shoot myself in the foot! But this time is different. This time, I f\*cked up so much that even the random commands on the internet could not help me. I was on my own and I needed to figure out what is wrong with my system. Let me tell you what I did:
I decided to install another OS just to try it in a real machine. I wanted to shrink one of my partitions to create a space for the new system. I run `fdisk /dev/sdb`, the very first message that it tells me was
> `This disk is currently in use - repartitioning is probably a bad idea. It's recommended to umount all file systems, and swapoff all swap partitions on this disk.`
Yes, it just screams ***"Do not do it!"*** but come on. I will not try to shrink the partition I am using (`sdb3`). So it should not be a problem. I ignored the message and shrink it anyway. No problem. Installed and tested the new OS a little bit. Time to reboot and hope for the best. And of course it did not boot. What would I even expecting?
![ah sh\*t here we go again](/assets/images/grub-rescue/cj.png)
As always, I booted into a live environment and run `boot-repair` command. It was always working but this time... Even after finishing the operation successfully I could not boot into neither Arch nor Ubuntu (the two systems I had previously).
Arch was originally mounted in `sdb3` and Ubuntu was in `sda2`. Considering the fact that I only messed with `sdb`, I should be able to boot Ubuntu, right? Well, yeah. Technically I did boot into Ubuntu but I didn't see the login screen. It was dropping me into something called *"Emergency mode"* which just makes me panic! `sudo update-grub`... Nope. Nothing changes. Arch does not boot and Ubuntu partially boots.
Let me tell you what the problem was and how my ignorance made it worse:
- While installing the new system, I saw a partition **labelled** *"Microsoft Basic Data"*. I deleted it thinking it is not required because I don't use W\*ndows. It turns out, it was my *boot* partition for Arch, just labelled incorrectly... Big lolz :D But we will see this is not even important because I had to rewrite my boot partition anyway.
- My Arch was installed in `sdb3`. When I created a new partition and installed the new system, `sdb3` was shifted to `sdb5` even though I did not ask for it. But the grub configuration to boot my system was still pointing to `sdb3`. That was the reason why Arch does not boot. It was trying to boot from `sdb3`. So I had to recreate grub configuration and reinstall grub to fix it. I run the following commands that I found [here](https://www.jeremymorgan.com/tutorials/linux/how-to-reinstall-boot-loader-arch-linux/) in a live Arch environment:
```bash
mkdir /mnt/arch
mount -t auto /dev/sdb5 /mnt/arch
arch-chroot /mnt/arch
mount -t auto /dev/sdb4 /boot/efi
os-prober
grub-mkconfig > /boot/grub/grub.cfg
grub-install --efi-directory=/boot/efi --target=x86_64-efi /dev/sdb
exit
reboot
```
And it fixed my grub. I can now boot into Arch, hooray!
- Ubuntu was not still booting properly. I checked the logs with `journalctl -xb` and saw something related with `sdb`. Ubuntu was installed in `sda2`, why `sdb` should be a problem? Then I remembered something. Back in times when I was using Ubuntu, I was using `sdb1` as a secondary storage. So I had a configuration where it automatically mounts `sdb1` on startup. Since I messed with `sdb1` , it was failing to mount it. I opened `/etc/fstab`, and deleted the related line. Bingo! It started booting properly.
![i am something of a hackerman myself](/assets/images/grub-rescue/hackerman.jpg)
- I started feeling like Hackerman, and I said to myself *"You know what, Imma fix everything."* I had a very sh\*tty grub menu with useless grub entries from old systems that I don't use anymore. The UEFI also had the same problem. It had ridiculous amount of boot entries that most of them are just trash.
![the pictures i took while trying to figure out which boot options are useless](/assets/images/grub-rescue/shitty-uefi.jpg)
These are the pictures I took for reference while trying to figure out which boot options are useless. Sorry for the bad quality. I didn't think I would use them in a blog post.
- While trying to fix the previous problems, I've spent enough time in the `/boot/efi` directory that make me understand where these grub entries are coming from. There were a lot of files belong to old systems. I simply deleted them and updated grub. All of the bad entries were gone. I want to draw your attention here: *I did not search for how to delete the unused grub entries. I just knew deleting their directories from `/boot/efi` will do the job. I am doing this sh\*t! (Another hackerman moment :D )*
- In order to delete useless boot options from UEFI menu, I used `efibootmgr`. I searched for it on the internet, of course!
```bash
efibootmgr -v # Check which entries you want to delete, say it is 0003.
sudo efibootmgr -b 0003 -B # This will delete third boot option.
```
And finally! I know everything about how all these work. Another shady part of Linux is clear for me. Now:
![Give me a ruined computer and an Arch ISO, and I shall fix it for you.](/assets/images/grub-rescue/quote.jpg)

View File

@ -1,26 +0,0 @@
---
title: "Confession Time"
date: 2022-04-08 18:46:00 +0300
last_modified_at: 2022-04-13
tags: ssl
---
## A failure story
Last week, I received an email from [Let's Encrypt](https://letsencrypt.org/) reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I can't send or receive any emails. If you send me email in the last week and wonder why I didn't respond, this is the reason.
Anyway, I thought it will be easy to fix. Just run `certbot` again and let him do the job, right? NOPE. It is not that easy. It is just giving me errors with some success messages. If I was not so clueless about what the heck I am doing, I could fix the error. But I don't know anything about how SSL works and it is a shame.
I don't even know the subject enough to Google it. I feel like I am the only guy in the planet whose certificate is expired. Seriously, how tf I can't find a solution to a such common problem? There was a saying like, *"If you can't find something on the internet, there is a high chance that you are being stupid"*. It was not exactly like this but I can't find the original quote either. Argghh...
If you know the original quote, email me... No, do not email because it does not work. F%ck this thing. F*%k everything. I deserved this. Do not help. If I can't fix this by myself, I should not call myself computer engineer. I am out.
### **Update**
The problem is fixed. One of my colleagues told me to reboot the server so that it will (*possibly*) trigger a script to get a new certificate. I did not think it would work because I already try to get a new certificate manually running `certbot renew`. And yeah, it didn't change anything but gave me courage to try other *dead simple* solutions.
- One of them was adding missing MX records for my domain. `certbot` was telling me that it can't find any `A` or `AAAA` records for `www.mail`. I didn't think this is related with my problem because how would I receive emails before then? Anyway, I added the records and the errors are gone. It was only giving me success messages now. Everything seemed to be fine. But I still could not connect to my mail account.
- And here is the solution: `sudo systemctl restart dovecot`. Kill me. I am *guessing* I had to restart the mail service because certificate has changed and it had to pick up the new one. I bet if I had run this command right after `certbot renew` I would not face any issues. The error messages caused by missing mx records were not related with this problem but I was confused by them and I thought something wrong with my certificates.
Any way, I am happy that it is finally fixed. Did I learn something from this? Not much. But yeah, sometimes all you need is a simple restart :D

View File

@ -1,34 +0,0 @@
---
title: "Rant: Stop whatever you are doing and learn how licenses work"
date: 2022-06-22 10:46:00 +0300
tags: copilot license github
---
Recently, Github [announced](https://github.blog/changelog/2022-06-21-github-copilot-is-now-available-to-individual-developers/)
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list.
When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it:
- Pay the subscription fee and get it.
- Prove you are a student and get it for free.
- Be a maintainer of *a popular repository* and get it for free.
I think I should be able to use it for free because I am a student but apparently they are not convinced yet. Anyways, that is a different
story. I don't care if they will give me access to Github Copilot or not. It is not a big deal for me.
But some people were really angry about how Github Team being vague while defining the criteria as "being a maintainer of a popular open source project".
I think they are right to some extent. If all you need is having a few thousands stars for a project, you could easily get that. I know a lot of troll
or low effort repositories that get a lot of stars because they are funny.
Later, I found [another tweet](https://twitter.com/fatih/status/1539574219629105156) that explains how Github decides what is *popular*. According to
this tweet, if you have a repository that is in top 1000 in one of the most popular 34 languages, you are eligible to get Github Copilot for free.
This is better than the previous definition but you can still argue that it is not fair because one can create a package for checking if a number is
even or not and get thousands of stars.
You can criticize this, I get that. But do not come up with silly arguments to justify yourself. Like how on earth would you think that Github is doing
something bad because $10/month is too much for this service? It is business man, you pay if you think it is worth it. That's it. *"I joined beta program
and it was free, now they want to charge me if I want to continue using it. They did not tell me that."* Uhhm... What? Are you aware that what you are using
is another company's service and they have all rights to do whatever they want with their service? How you guys even can build up arguments like that?! This is crazy!
Some people argue that *"what Github is doing is wrong because they used open source projects **without consent**."* Another similar argument is that *"what
Github is doing is evil because they used projects developed by community and now they are selling it without giving any money to the contributors of
these projects."* Do you guys even have an idea what licenses stands for? If you don't want to some random person use your code, just license it that
way. And if you licensed it with a GPL compatible or similar license you already gave rights anyone to use or sell your code. That is not Github's
problem. That is your problem not understanding how licenses work. Stop complaining.

View File

@ -1,19 +0,0 @@
---
title: "Recap of 2022"
date: 2022-12-29 23:22:08 +0300
---
It's been a while… It has been so long that I forgot how I was writing my blogs back then. My life didn't change that much. Actually, it is getting worse.
The biggest problem of my life is the graduation project. Oh, God it is making me sick! I simply don't have any interest for the subject I am supposed to work on. One part of me saying that "come on, you came this far. You are nearly finished. One last push!" and other part of me saying "oh no, don't do it. You have never done something you don't like in your entire life. F\*ck it!". So I am wasting my time each term with the dilemma I just described. I really don't know what to do. This thing is f'ed up.
Second biggest problem is I live in Turkey. I feel like all my friends somehow get rid of this sh\*thole and I am locked here. I use Twitter and Reddit to consume daily news and almost everyday I encounter something that make me say "F\*ck me, why I am still here? There is no hope". Actually, the situation was much worse while I was following pages that shares "street interviews". At first I started watching them *for fun* but the stupidity of people was real and harming my mental health. Since that day, I started consuming only news. My experience got better but I feel like it is still affecting me in a bad manner because everyday something bad happens and there is not much I can do to fix. Today, I decided to delete Twitter and Reddit. I'll see how it goes.
I am living with my parents for the past 6 months, I break up with my girlfriend, I left the place I was working. Man, this could be the worst year of my life!
![Jackie Chan WTF meme](/assets/images/recap-2022/jackie-chan-wtf.jpg)
You know what? I am not gonna give up. *"… It ain't about how hard you get hit. It's about how hard you get hit and keep moving forward. How much you can take, and keep moving forward…"* No, seriously things really will be different for me in 2023 I can feel it. I learn from my mistakes, they are making me even more perfect :D I love myself, I got this.
![Disaster girl saying "I got this"](/assets/images/recap-2022/i-got-this.jpg)

View File

@ -1,242 +0,0 @@
---
title: "Hot-Reload Long Running Shell Scripts (feat. trap / kill)"
date: 2023-01-16 00:48:08 +0300
tags: trap kill linux
---
## `trap` them and `kill` them!
There is a beautiful command in Linux called [`trap`](https://man7.org/linux/man-pages/man1/trap.1p.html) which *trap*s signals and let you run specific commands when they invoked. There is also good ol' [`kill`](https://man7.org/linux/man-pages/man1/kill.1.html) command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!
### Basic Example
Let's start by creating something very simple and build up from there. Create a script with the following contents:
```bash
#!/bin/bash
echo "My pid is $$. Send me SIGUSR1!"
func() {
echo "Got SIGUSR1"
}
# here we are telling that run 'func' when USR1 signal is
# received. You can run anything. Combine commands with ; etc.
trap "func" USR1
# The while loop is important here otherwise our script will exit
# before we manage to get a chance to send a signal.
while true ; do
echo "waiting SIGUSR1"
sleep 1
done
```
Now make it executable and run it:
```bash
chmod +x trap_example
./trap_example
My pid is 2811137. Send me SIGUSR1!
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
```
Open another terminal and send your signal with `kill` to the specified pid.
```bash
kill -s USR1 2811137
```
You should receive `"Got SIGUSR!"` from the other process. That's it! Now, imagine you write whatever thing you want to execute in `func` and then you can simply `kill -s ...` anytime and as many times you want!
Let's move the while loop into the `func` and add some variables so you can see how powerful this is.
```bash
#!/bin/bash
echo "My pid is $$. Send me SIGUSR1!"
func() {
i=1
while true ; do
echo "i: $i"
i=$(( i + 1 ))
sleep 1
done
}
trap "echo 'Got SIGUSR1!'; func" USR1
# we need to call the function once, otherwise script
# will exit before we manage to send a signal
func
```
Now run the script and send `SIGUSR1`. Here is the result:
```bash
./trap_example
My pid is 2880704. Send me SIGUSR1!
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
Got SIGUSR1!
i: 1
i: 2
i: 3
i: 4
i: 5
Got SIGUSR1!
i: 1
i: 2
^C
```
Isn't this neat?
### More useful example
Let's imagine you have multiple long running (infinite loops basically) scripts and you want to restart them without manually searching for their pid's and killing them. `trap` is for the rescue, again! <sup>[*](## "Yeah, I know you can run a systemd service if you want but I think it is an overkill for this situation. Plus, I don't like dealing with them.")</sup> This command is awesome.
Without further ado, let's get started. Create a script called `script1` with the following contents:
```bash
#!/bin/bash
# file: script1
i=1
while true ; do
echo "Hello from $0. i is $i"
i=$(( i + 1 ))
sleep 1
done
```
And symlink it to another name just for fun:
```bash
chmod +x script1
ln -s script1 script2
```
Now we can pretend they are two different scripts as their outputs differ:
```bash
./script1
Hello from ./script1. i is 1
Hello from ./script1. i is 2
Hello from ./script1. i is 3
Hello from ./script1. i is 4
^C
./script2
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script2. i is 3
^C
```
Finally, create the main script which will start child scripts and restart them on our signals:
```bash
#!/bin/bash
echo "My pid is $$. You know what to do ( ͡° ͜ʖ ͡°)"
echo "You can also kill me with 'kill -s INT -\`pgrep -f `basename $0`\`'"
pids=() # we will store the pid's of child scripts here
scripts_to_be_executed=("./script1" "./script2")
kill_childs(){ # wow, this sounded wild
for pid in "${pids[@]}"
do
echo killing "$pid"
# -P: kill all the processes whose parent process is 'pid'
# see how we are creating processes below
pkill -P "$pid"
done
pids=()
}
# kill childs and restart all the scripts
restart_scripts(){
kill_childs
# for each script in the list
for script in "${scripts_to_be_executed[@]}"
do
# Run the script and store its pid.
# note the '&' at the end of command. Without it the script will
# block until its execution is finished. Also we are putting it
# into braces because we want to create a "process group" so that
# we can kill all its children later by specifying parent pid
# (useful if you have pipes (|) or other &'s in your script!)
($script) &
pids+=("$!")
done
}
# we will restart_scripts with SIGUSR1 signal
trap 'echo "restarting scripts"; restart_scripts' USR1
# we will kill all the childs and exit the main script with SIGINT
# which is same signal as when you press <Control-C> on your terminal
trap 'echo exiting; kill_childs; exit' INT
# run the function once
restart_scripts
# infinite loop, otherwise main script will exit before we send signal.
# remember, we started child processes with '&' so they won't block this script
while true; do
sleep 1
done
```
Now, you can run your main script and reload your child scripts any time with `killall main_script -USR1`
Here is an example run:
```
./trap_multiple
My pid is 3124123. You know what to do ( ͡° ͜ʖ ͡°)
You can also kill me with 'kill -s INT -`pgrep -f trap_multiple`'
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script1. i is 2
Hello from ./script2. i is 3
Hello from ./script1. i is 3
restarting scripts
killing 3124125
killing 3124126
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script1. i is 2
Hello from ./script2. i is 3
Hello from ./script1. i is 3
Hello from ./script2. i is 4
Hello from ./script1. i is 4
restarting scripts
killing 3124304
killing 3124305
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script1. i is 2
Hello from ./script2. i is 2
^Cexiting
killing 3124875
killing 3124876
```
### Final words
I think I am started to getting obsessed with `trap` command because it has such a good name and purpose. FOSS people are really on another level when it comes to naming. Here is another good one:
> \- How can you see the contents of a file? <br>
\+ You *`cat`* it. <br>
\- What if you want to see them in reverse order? <br>
\+ You *`tac`* it. <br>
No, it is not just a joke. Try it... Man I love Gnoo slash Linux.
Anyway, I hope now you know how to `trap` and `kill`. Next week I will explain how to `unzip; strip; touch; finger; grep; mount; fsck; more; yes; fsck; fsck; umount; clean; sleep` <nobr>( ͡° ͜ʖ ͡°)</nobr>. <sup>[*](## "jk :D")</sup>

View File

@ -1,5 +0,0 @@
.ab {
font-size: 1.5em;
line-height:0;
top:0
}

View File

@ -1,30 +0,0 @@
---
layout: single
title: About
permalink: /about/
---
Hi, my name is **Şahin Akkaya**. I am a 4th year student studying
Computer Engineering at [ITU][itu]. I am a Free Software enthusiast,
Python lover and perfectionist. I like to tinker things until they
are *just right*. I also believe there is no such thing as perfect so
I never stop. I will do my best to make things better and I love doing
it so far.
> Roses are red \\
Violets are blue \\
There will be always \\
A better tool for you \\
\\
> <cite>Şahin Akkaya</cite>
Subscribe to my <a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i>RSS Feed</a> for most recent gems like this
(kidding). But I can still give you three good reason to subscribe:
1. You are here. Reading something on my website. So you wonder about
me.
2. I did literally nothing to set up the feed. It is built in to
[Jekyll][jekyll].
3. RSS is the best thing in the world. Why not?
[itu]: https://www.itu.edu.tr/
[jekyll]: https://jekyllrb.com/

403
about/index.html 100644
View File

@ -0,0 +1,403 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>About - Şahin Akkayas Personal Page</title>
<meta name="description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<meta name="author" content="Şahin Akkaya">
<meta property="og:type" content="website">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="About">
<meta property="og:url" content="https://sahinakkaya.dev/about/">
<meta property="og:description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<link rel="canonical" href="https://sahinakkaya.dev/about/">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="About">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">About
</h1>
</header>
<section class="page__content" itemprop="text">
<p>Hi, my name is <strong>Şahin Akkaya</strong>. I am a 4th year student studying
Computer Engineering at <a href="https://www.itu.edu.tr/">ITU</a>. I am a Free Software enthusiast,
Python lover and perfectionist. I like to tinker things until they
are <em>just right</em>. I also believe there is no such thing as perfect so
I never stop. I will do my best to make things better and I love doing
it so far.</p>
<blockquote>
<p>Roses are red <br>
Violets are blue <br>
There will be always <br>
A better tool for you <br>
<br>
<cite>Şahin Akkaya</cite></p>
</blockquote>
<p>Subscribe to my <a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i>RSS Feed</a> for most recent gems like this
(kidding). But I can still give you three good reason to subscribe:</p>
<ol>
<li>You are here. Reading something on my website. So you wonder about
me.</li>
<li>I did literally nothing to set up the feed. It is built in to
<a href="https://jekyllrb.com/">Jekyll</a>.</li>
<li>RSS is the best thing in the world. Why not?</li>
</ol>
</section>
<footer class="page__meta">
</footer>
</div>
</article>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

1693
assets/css/main.css 100644

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,32 +0,0 @@
---
# Only the main Sass file needs front matter (the dashes are enough)
---
$base00: #1e0f15;
$base01: #2e3c43;
$base02: #314549;
$base03: #546e7a;
$base04: #b2ccd6;
$base05: #eeffff;
$base06: #eeffff;
$base07: #ffffff;
$base08: #f07178;
$base09: #f78c6c;
$base0a: #ffcb6b;
$base0b: #c3e88d;
$base0c: #89ddff;
$base0d: #82aaff;
$base0e: #c792ea;
$base0f: #ff5370;
$code-background-color: mix($base00, $base01, 80%);
$code-background-color-dark: mix($base00, $base01, 85%);
@import "minimal-mistakes/skins/{{ site.minimal_mistakes_skin | default: 'default' }}"; // skin
@import "minimal-mistakes"; // main partials
::selection{
background: #004DAA;
}

View File

@ -13,18 +13,18 @@ EW21/il4ANrLjP6BQSUKG4UwlNxeTaYR0raGme27Uc/zIfkVOI+d5eAk0JvTz4MG
7ytQmyNHYQ2B39xPQQBZF4GnckFHkw01/Pzejwvf9bH7tBVJA5de6xMBSQARAQAB
tC7FnmFoaW4gQWtrYXlhIChBc29jaWEpIDxzYWhpbkBzYWhpbmFra2F5YS5kZXY+
iQJUBBMBCAA+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEqJwgAzRa8I9M
g0tPHIjb5s2hXtIFAmU43AkFCQQ1BFUACgkQHIjb5s2hXtLcnA/+MB5os5cqQT2a
OoGnDgI5X9PxEcOTXeigCZn925xul1CKEcdPQadRVpkwFhpU5A8bq7ph63ZRc2CC
Q41met6SDIkdoON9YK1UdEolBbD4XgcRK+7/qbnkB2ih5zDVa3+pCsyv59UvyMJN
UmpZ4lK1g5fismEEp+BdsINyIY1jMtVUym5STFqAY9n0WEOAavu9umUandjUVBUM
gdWvlocdKCNI89RnecuvZJvTDWJ80/m+iz42LpbErdGlqazDkANGCGHaowM04ebc
zbf9tIh+KAGBwcmgV2Hl15jFOEKMrpLxfmXSBbAnvtvr88SXqyE74MBxHfNULnDX
NOWZ1F8CT9Z7lZ8cvvFFufaiozc9CbQx1fTLQNJEIoXbtlAZS3YH5Bcp5RBLg2R+
gTXLwZwHvIwzuKKCoG2pF0MMMdOx7VxUs8I8VKOf3cUO9O/gOub5Uoj/v7wchrW2
6md8rPqzMS9BpvnzqTyncdrcE8ZMoy3+UBICcwdEBb3ZRWWoj95O/ppQowxYiDP3
XfBQUDVhh9tuscjUvwg+cBwREnZ7zUKLXnpjbQRBR2FEXUBWTkTKSjnpXg09CRVD
s7S74ysZoxBxo4SrnqNJfXZHS+b4fTgor/hGp1rBY1U0UCNt2jP3v+ttyElEhYdA
m+UbT5kvY8JZb/cy2rGnZ1V5/h3hidqJAlQEEwEIAD4WIQSonCADNFrwj0yDS08c
g0tPHIjb5s2hXtIFAmJExywFCQI01PgACgkQHIjb5s2hXtLT+Q/+MgUDUBBzYr6H
ZlYXCo/YfoP/OuuNlqyt/h/Pfp+iHI/IG+NTeJFp0e1pxnB7z9WKlO+iXz2O7uZm
mPeZToEtoHon7CDVfsFEYrDmKtA93e5RxUA6LxdBx3k+n60MgjiGYLF1Ygo1QQ/u
BFGEPfNRBSGsyiCvxMjLuImzRf3YQz03Esn4ph7DiWOiclpedEx9QBgnDCvJenG0
aM17qbucL+2OqVxzZ2xI1Vb3wawftS4jwVyGaWGhc01eNdEIjWys37dunqNriC76
TqV8VOplKAxf4/gJT8L/m1k4vZfqX4u5Ff1xVQIyOq49fXFMvWMS34k8w4guQ9s2
Z4ik95sn4fS3mm/WaLL08bUwFFNF8Q+m2orjdGSvGOmAmMHbGgxpwgZkJqPeKCrk
6F24fZ4ko7oZ+FhsvLEZwagYyItQl65t8eBCBynpyrG1GrfgcKXM6UKRW1PWqsB6
iXpP6maa9l58zXxX0XlEYKCH6+rYdJkgM4FWegfScu4fYM3E7Kdb8hJ8hPu32sMt
HmFJxChl0bJSyqRGAe8Z4fd0fUkGGM/GmE5pEI2CgtKWj+95EGcslBnbkSA5K1La
lBze/JaLGg0XZHHKmKKFrAG20IA7kCB5VellR63vcRW0QqhEkR1g7xap+uM4idFq
9fFN/4IJu57DsWvBCr+d9c9iWIlGxNiJAlQEEwEIAD4WIQSonCADNFrwj0yDS08c
iNvmzaFe0gUCYfEltAIbAwUJAAk6gAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAK
CRAciNvmzaFe0lMXD/9C+ffRNp0nscSpUq56EoRKRvrzUcR+orNT/7e3bTbLj6pG
/z7jzAJC4akwaLa7FpVkKgNt5w1v+VBpKhBupQb5NuJCslmckfuE1PQ88Q3gGW5T
@ -48,17 +48,17 @@ TRK47b7R/MqekllvNTvPdB18X6NAT9oFI5oVm3keEJGMNhH66jkiilxtzPay6Ezq
BQWrm3NmkcuHEQUJyladUWyZv7CUQQYszIjZs/e3zZI/NKgZ/k+N6YVb5zfIDq/2
A9UFgLMQ9i0DPnElTojjzVsL8Nb6ehc70CWmiwIwESHtP/6QZuJZuD5sGredIZLK
OorEEWzHPflW0h8aZ+VE9KEOV7KLkovXQ1EY0NHHW++XrVVowUBE/pkAEQEAAYkC
PAQYAQgAJgIbDBYhBKicIAM0WvCPTINLTxyI2+bNoV7SBQJlONxYBQkENQSkAAoJ
EByI2+bNoV7S714P/jAIzVeeZG2svtra1TlC2hqMAMTNzH9Figssg9xDkgKsgPKr
r6HVi5W5oqUf5JNL0QGiEbUN1GPDAiB4Dm0QhGUrG1RPeND5M038MYYDumQMKI6E
eSszI8ZkrU9Wemxu4tLcOpRJGFhkw+YNb2V4djCFc27dgP4Bg23/XyTwB8zXqJWp
ZAPMOm3uWeVsT+8HsQ6rbDUXmQZpDrrD5zEFJgbqwVpdMXZlb4lj5XGhFObWdZY3
pDZtpcxSVkAbNmbbeK28mhl7Fmuu/5LcIyKrNVu9FB0gg6kKi74EqdBhhTyMLReB
SHwauqAthnordx8K5ENVZ1qPM7UXOU5TXeG4JKcYQQTarnp5lkYWJM2xGHmdBol7
V0UGKcIaaqwORqJqbOsWGPGcjWgYcPinzhu/yRINaWxhSve02RFI0Lh3oV/idYaZ
7wzNPaKf9MlC2Q3QqWBaLNvHsNydgK+j+I3xdvgY3HqCe3JBqRG6FscMh6r7rHyG
rDKYo+tqERkZRbhYfAbsi9pKQzpD8UTNaYdn0MEqvmayTIFGW95NJIIl89seQ/5O
kyjLdUsZkyTBIIdfO7GnXsVggezbVw/z2fpW415+2Qie7oWbz0H7f7Ltn6fISgJc
g5lmlH+DnhuI2JEPE36dMrCaf1FSoM5oN/gnmzOl4aSY8CaqHzKTqZmDxizb
=MHqa
PAQYAQgAJgIbDBYhBKicIAM0WvCPTINLTxyI2+bNoV7SBQJiRMddBQkCNNUpAAoJ
EByI2+bNoV7SIvAP/2tUM0jMn2o+DW6JQyOQdRSgVLWoUDiHg27MKsudYEVFdbTA
uR+NjnTGMd2sqK8cFAQ7B+897hV/WtqS+PYL8bK/5b+ze3AjYjiL6lNYb4VW5Vw9
EW+kTrcnKRS/bzZC4vXFOyK/Zb2VQifv6XMjrC6Mf/oC1c2sXCh7CYkHAo8V3q98
6tNtfPFMzcetfTaEA5ng7g9UkAjCAWPXCk7x9PdBc6FyA5ER+fAr05VjaezcJVut
nJhSxYZJSXy3dZ5+tpYZ+f8U+N60g0WjP2DOHi0ErbwIRrJOxoaunpkpBxhKIor0
c/LN3tUM7NnJpI4h1BMMMf3aHi2NKUp61Bm1ba2ELdw9iJsMvxCAVGy314mp/EAL
2gHynumOABzIRfhcxeG1c+9yuulULpoyJWQwxFDKwCWmho9uxoXW9ssZ9B46bjfG
7Tq1QH5nAy6Bc5XACxwAAC9PRXYaQ9GNQSuGZdR3xjCE+XEprkfi62EX2U6qYcUi
SBlo8z88qE9piRx9+pVUJCIfC4MUgqqYnOQL/m6QjNqk2hlR3xgknfEm6+QvDy2c
9lYg7teYslpuNhpeRa+vzTRbs5p3cIbvqwZlzqL1joBsDj9UYLh7BqfOBSyefzGh
go/zsDeCRPKU2QM53h3PvZvZvZ9y0KEN+a+dPEhbgfdjsSOWZ77KvnEqxgZk
=gAav
-----END PGP PUBLIC KEY BLOCK-----

Binary file not shown.

136
assets/js/_main.js 100644
View File

@ -0,0 +1,136 @@
/* ==========================================================================
jQuery plugin settings and other scripts
========================================================================== */
$(document).ready(function() {
// FitVids init
$("#main").fitVids();
// Sticky sidebar
var stickySideBar = function() {
var show =
$(".author__urls-wrapper button").length === 0
? $(window).width() > 1024 // width should match $large Sass variable
: !$(".author__urls-wrapper button").is(":visible");
if (show) {
// fix
$(".sidebar").addClass("sticky");
} else {
// unfix
$(".sidebar").removeClass("sticky");
}
};
stickySideBar();
$(window).resize(function() {
stickySideBar();
});
// Follow menu drop down
$(".author__urls-wrapper button").on("click", function() {
$(".author__urls").toggleClass("is--visible");
$(".author__urls-wrapper button").toggleClass("open");
});
// Close search screen with Esc key
$(document).keyup(function(e) {
if (e.keyCode === 27) {
if ($(".initial-content").hasClass("is--hidden")) {
$(".search-content").toggleClass("is--visible");
$(".initial-content").toggleClass("is--hidden");
}
}
});
// Search toggle
$(".search__toggle").on("click", function() {
$(".search-content").toggleClass("is--visible");
$(".initial-content").toggleClass("is--hidden");
// set focus on input
setTimeout(function() {
$(".search-content input").focus();
}, 400);
});
// Smooth scrolling
var scroll = new SmoothScroll('a[href*="#"]', {
offset: 20,
speed: 400,
speedAsDuration: true,
durationMax: 500
});
// Gumshoe scroll spy init
if($("nav.toc").length > 0) {
var spy = new Gumshoe("nav.toc a", {
// Active classes
navClass: "active", // applied to the nav list item
contentClass: "active", // applied to the content
// Nested navigation
nested: false, // if true, add classes to parents of active link
nestedClass: "active", // applied to the parent items
// Offset & reflow
offset: 20, // how far from the top of the page to activate a content area
reflow: true, // if true, listen for reflows
// Event support
events: true // if true, emit custom events
});
}
// add lightbox class to all image links
$(
"a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif'],a[href$='.webp']"
).addClass("image-popup");
// Magnific-Popup options
$(".image-popup").magnificPopup({
// disableOn: function() {
// if( $(window).width() < 500 ) {
// return false;
// }
// return true;
// },
type: "image",
tLoading: "Loading image #%curr%...",
gallery: {
enabled: true,
navigateByImgClick: true,
preload: [0, 1] // Will preload 0 - before current, and 1 after the current image
},
image: {
tError: '<a href="%url%">Image #%curr%</a> could not be loaded.'
},
removalDelay: 500, // Delay in milliseconds before popup is removed
// Class that is added to body when popup is open.
// make it unique to apply your CSS animations just to this exact popup
mainClass: "mfp-zoom-in",
callbacks: {
beforeOpen: function() {
// just a hack that adds mfp-anim class to markup
this.st.image.markup = this.st.image.markup.replace(
"mfp-figure",
"mfp-figure mfp-with-anim"
);
}
},
closeOnContentClick: true,
midClick: true // allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source.
});
// Add anchors for headings
$('.page__content').find('h1, h2, h3, h4, h5, h6').each(function() {
var id = $(this).attr('id');
if (id) {
var anchor = document.createElement("a");
anchor.className = 'header-link';
anchor.href = '#' + id;
anchor.innerHTML = '<span class=\"sr-only\">Permalink</span><i class=\"fas fa-link\"></i>';
anchor.title = "Permalink";
$(this).append(anchor);
}
});
});

View File

@ -0,0 +1,69 @@
var idx = lunr(function () {
this.field('title')
this.field('excerpt')
this.field('categories')
this.field('tags')
this.ref('id')
this.pipeline.remove(lunr.trimmer)
for (var item in store) {
this.add({
title: store[item].title,
excerpt: store[item].excerpt,
categories: store[item].categories,
tags: store[item].tags,
id: item
})
}
});
$(document).ready(function() {
$('input#search').on('keyup', function () {
var resultdiv = $('#results');
var query = $(this).val().toLowerCase();
var result =
idx.query(function (q) {
query.split(lunr.tokenizer.separator).forEach(function (term) {
q.term(term, { boost: 100 })
if(query.lastIndexOf(" ") != query.length-1){
q.term(term, { usePipeline: false, wildcard: lunr.Query.wildcard.TRAILING, boost: 10 })
}
if (term != ""){
q.term(term, { usePipeline: false, editDistance: 1, boost: 1 })
}
})
});
resultdiv.empty();
resultdiv.prepend('<p class="results__found">'+result.length+' Result(s) found</p>');
for (var item in result) {
var ref = result[item].ref;
if(store[ref].teaser){
var searchitem =
'<div class="list__item">'+
'<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">'+
'<h2 class="archive__item-title" itemprop="headline">'+
'<a href="'+store[ref].url+'" rel="permalink">'+store[ref].title+'</a>'+
'</h2>'+
'<div class="archive__item-teaser">'+
'<img src="'+store[ref].teaser+'" alt="">'+
'</div>'+
'<p class="archive__item-excerpt" itemprop="description">'+store[ref].excerpt.split(" ").splice(0,20).join(" ")+'...</p>'+
'</article>'+
'</div>';
}
else{
var searchitem =
'<div class="list__item">'+
'<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">'+
'<h2 class="archive__item-title" itemprop="headline">'+
'<a href="'+store[ref].url+'" rel="permalink">'+store[ref].title+'</a>'+
'</h2>'+
'<p class="archive__item-excerpt" itemprop="description">'+store[ref].excerpt.split(" ").splice(0,20).join(" ")+'...</p>'+
'</article>'+
'</div>';
}
resultdiv.append(searchitem);
}
});
});

View File

@ -0,0 +1,522 @@
step1list = new Array();
step1list["ΦΑΓΙΑ"] = "ΦΑ";
step1list["ΦΑΓΙΟΥ"] = "ΦΑ";
step1list["ΦΑΓΙΩΝ"] = "ΦΑ";
step1list["ΣΚΑΓΙΑ"] = "ΣΚΑ";
step1list["ΣΚΑΓΙΟΥ"] = "ΣΚΑ";
step1list["ΣΚΑΓΙΩΝ"] = "ΣΚΑ";
step1list["ΟΛΟΓΙΟΥ"] = "ΟΛΟ";
step1list["ΟΛΟΓΙΑ"] = "ΟΛΟ";
step1list["ΟΛΟΓΙΩΝ"] = "ΟΛΟ";
step1list["ΣΟΓΙΟΥ"] = "ΣΟ";
step1list["ΣΟΓΙΑ"] = "ΣΟ";
step1list["ΣΟΓΙΩΝ"] = "ΣΟ";
step1list["ΤΑΤΟΓΙΑ"] = "ΤΑΤΟ";
step1list["ΤΑΤΟΓΙΟΥ"] = "ΤΑΤΟ";
step1list["ΤΑΤΟΓΙΩΝ"] = "ΤΑΤΟ";
step1list["ΚΡΕΑΣ"] = "ΚΡΕ";
step1list["ΚΡΕΑΤΟΣ"] = "ΚΡΕ";
step1list["ΚΡΕΑΤΑ"] = "ΚΡΕ";
step1list["ΚΡΕΑΤΩΝ"] = "ΚΡΕ";
step1list["ΠΕΡΑΣ"] = "ΠΕΡ";
step1list["ΠΕΡΑΤΟΣ"] = "ΠΕΡ";
step1list["ΠΕΡΑΤΑ"] = "ΠΕΡ";
step1list["ΠΕΡΑΤΩΝ"] = "ΠΕΡ";
step1list["ΤΕΡΑΣ"] = "ΤΕΡ";
step1list["ΤΕΡΑΤΟΣ"] = "ΤΕΡ";
step1list["ΤΕΡΑΤΑ"] = "ΤΕΡ";
step1list["ΤΕΡΑΤΩΝ"] = "ΤΕΡ";
step1list["ΦΩΣ"] = "ΦΩ";
step1list["ΦΩΤΟΣ"] = "ΦΩ";
step1list["ΦΩΤΑ"] = "ΦΩ";
step1list["ΦΩΤΩΝ"] = "ΦΩ";
step1list["ΚΑΘΕΣΤΩΣ"] = "ΚΑΘΕΣΤ";
step1list["ΚΑΘΕΣΤΩΤΟΣ"] = "ΚΑΘΕΣΤ";
step1list["ΚΑΘΕΣΤΩΤΑ"] = "ΚΑΘΕΣΤ";
step1list["ΚΑΘΕΣΤΩΤΩΝ"] = "ΚΑΘΕΣΤ";
step1list["ΓΕΓΟΝΟΣ"] = "ΓΕΓΟΝ";
step1list["ΓΕΓΟΝΟΤΟΣ"] = "ΓΕΓΟΝ";
step1list["ΓΕΓΟΝΟΤΑ"] = "ΓΕΓΟΝ";
step1list["ΓΕΓΟΝΟΤΩΝ"] = "ΓΕΓΟΝ";
v = "[ΑΕΗΙΟΥΩ]";
v2 = "[ΑΕΗΙΟΩ]"
function stemWord(w) {
var stem;
var suffix;
var firstch;
var origword = w;
test1 = new Boolean(true);
if(w.length < 4) {
return w;
}
var re;
var re2;
var re3;
var re4;
re = /(.*)(ΦΑΓΙΑ|ΦΑΓΙΟΥ|ΦΑΓΙΩΝ|ΣΚΑΓΙΑ|ΣΚΑΓΙΟΥ|ΣΚΑΓΙΩΝ|ΟΛΟΓΙΟΥ|ΟΛΟΓΙΑ|ΟΛΟΓΙΩΝ|ΣΟΓΙΟΥ|ΣΟΓΙΑ|ΣΟΓΙΩΝ|ΤΑΤΟΓΙΑ|ΤΑΤΟΓΙΟΥ|ΤΑΤΟΓΙΩΝ|ΚΡΕΑΣ|ΚΡΕΑΤΟΣ|ΚΡΕΑΤΑ|ΚΡΕΑΤΩΝ|ΠΕΡΑΣ|ΠΕΡΑΤΟΣ|ΠΕΡΑΤΑ|ΠΕΡΑΤΩΝ|ΤΕΡΑΣ|ΤΕΡΑΤΟΣ|ΤΕΡΑΤΑ|ΤΕΡΑΤΩΝ|ΦΩΣ|ΦΩΤΟΣ|ΦΩΤΑ|ΦΩΤΩΝ|ΚΑΘΕΣΤΩΣ|ΚΑΘΕΣΤΩΤΟΣ|ΚΑΘΕΣΤΩΤΑ|ΚΑΘΕΣΤΩΤΩΝ|ΓΕΓΟΝΟΣ|ΓΕΓΟΝΟΤΟΣ|ΓΕΓΟΝΟΤΑ|ΓΕΓΟΝΟΤΩΝ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
w = stem + step1list[suffix];
test1 = false;
}
re = /^(.+?)(ΑΔΕΣ|ΑΔΩΝ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
reg1 = /(ΟΚ|ΜΑΜ|ΜΑΝ|ΜΠΑΜΠ|ΠΑΤΕΡ|ΓΙΑΓΙ|ΝΤΑΝΤ|ΚΥΡ|ΘΕΙ|ΠΕΘΕΡ)$/;
if(!(reg1.test(w))) {
w = w + "ΑΔ";
}
}
re2 = /^(.+?)(ΕΔΕΣ|ΕΔΩΝ)$/;
if(re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
w = stem;
exept2 = /(ΟΠ|ΙΠ|ΕΜΠ|ΥΠ|ΓΗΠ|ΔΑΠ|ΚΡΑΣΠ|ΜΙΛ)$/;
if(exept2.test(w)) {
w = w + "ΕΔ";
}
}
re3 = /^(.+?)(ΟΥΔΕΣ|ΟΥΔΩΝ)$/;
if(re3.test(w)) {
var fp = re3.exec(w);
stem = fp[1];
w = stem;
exept3 = /(ΑΡΚ|ΚΑΛΙΑΚ|ΠΕΤΑΛ|ΛΙΧ|ΠΛΕΞ|ΣΚ|Σ|ΦΛ|ΦΡ|ΒΕΛ|ΛΟΥΛ|ΧΝ|ΣΠ|ΤΡΑΓ|ΦΕ)$/;
if(exept3.test(w)) {
w = w + "ΟΥΔ";
}
}
re4 = /^(.+?)(ΕΩΣ|ΕΩΝ)$/;
if(re4.test(w)) {
var fp = re4.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept4 = /^(Θ|Δ|ΕΛ|ΓΑΛ|Ν|Π|ΙΔ|ΠΑΡ)$/;
if(exept4.test(w)) {
w = w + "Ε";
}
}
re = /^(.+?)(ΙΑ|ΙΟΥ|ΙΩΝ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
re2 = new RegExp(v + "$");
test1 = false;
if(re2.test(w)) {
w = stem + "Ι";
}
}
re = /^(.+?)(ΙΚΑ|ΙΚΟ|ΙΚΟΥ|ΙΚΩΝ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
re2 = new RegExp(v + "$");
exept5 = /^(ΑΛ|ΑΔ|ΕΝΔ|ΑΜΑΝ|ΑΜΜΟΧΑΛ|ΗΘ|ΑΝΗΘ|ΑΝΤΙΔ|ΦΥΣ|ΒΡΩΜ|ΓΕΡ|ΕΞΩΔ|ΚΑΛΠ|ΚΑΛΛΙΝ|ΚΑΤΑΔ|ΜΟΥΛ|ΜΠΑΝ|ΜΠΑΓΙΑΤ|ΜΠΟΛ|ΜΠΟΣ|ΝΙΤ|ΞΙΚ|ΣΥΝΟΜΗΛ|ΠΕΤΣ|ΠΙΤΣ|ΠΙΚΑΝΤ|ΠΛΙΑΤΣ|ΠΟΣΤΕΛΝ|ΠΡΩΤΟΔ|ΣΕΡΤ|ΣΥΝΑΔ|ΤΣΑΜ|ΥΠΟΔ|ΦΙΛΟΝ|ΦΥΛΟΔ|ΧΑΣ)$/;
if((exept5.test(w)) || (re2.test(w))) {
w = w + "ΙΚ";
}
}
re = /^(.+?)(ΑΜΕ)$/;
re2 = /^(.+?)(ΑΓΑΜΕ|ΗΣΑΜΕ|ΟΥΣΑΜΕ|ΗΚΑΜΕ|ΗΘΗΚΑΜΕ)$/;
if(w == "ΑΓΑΜΕ") {
w = "ΑΓΑΜ";
}
if(re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
w = stem;
test1 = false;
}
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept6 = /^(ΑΝΑΠ|ΑΠΟΘ|ΑΠΟΚ|ΑΠΟΣΤ|ΒΟΥΒ|ΞΕΘ|ΟΥΛ|ΠΕΘ|ΠΙΚΡ|ΠΟΤ|ΣΙΧ|Χ)$/;
if(exept6.test(w)) {
w = w + "ΑΜ";
}
}
re2 = /^(.+?)(ΑΝΕ)$/;
re3 = /^(.+?)(ΑΓΑΝΕ|ΗΣΑΝΕ|ΟΥΣΑΝΕ|ΙΟΝΤΑΝΕ|ΙΟΤΑΝΕ|ΙΟΥΝΤΑΝΕ|ΟΝΤΑΝΕ|ΟΤΑΝΕ|ΟΥΝΤΑΝΕ|ΗΚΑΝΕ|ΗΘΗΚΑΝΕ)$/;
if(re3.test(w)) {
var fp = re3.exec(w);
stem = fp[1];
w = stem;
test1 = false;
re3 = /^(ΤΡ|ΤΣ)$/;
if(re3.test(w)) {
w = w + "ΑΓΑΝ";
}
}
if(re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
w = stem;
test1 = false;
re2 = new RegExp(v2 + "$");
exept7 = /^(ΒΕΤΕΡ|ΒΟΥΛΚ|ΒΡΑΧΜ|Γ|ΔΡΑΔΟΥΜ|Θ|ΚΑΛΠΟΥΖ|ΚΑΣΤΕΛ|ΚΟΡΜΟΡ|ΛΑΟΠΛ|ΜΩΑΜΕΘ|Μ|ΜΟΥΣΟΥΛΜ|Ν|ΟΥΛ|Π|ΠΕΛΕΚ|ΠΛ|ΠΟΛΙΣ|ΠΟΡΤΟΛ|ΣΑΡΑΚΑΤΣ|ΣΟΥΛΤ|ΤΣΑΡΛΑΤ|ΟΡΦ|ΤΣΙΓΓ|ΤΣΟΠ|ΦΩΤΟΣΤΕΦ|Χ|ΨΥΧΟΠΛ|ΑΓ|ΟΡΦ|ΓΑΛ|ΓΕΡ|ΔΕΚ|ΔΙΠΛ|ΑΜΕΡΙΚΑΝ|ΟΥΡ|ΠΙΘ|ΠΟΥΡΙΤ|Σ|ΖΩΝΤ|ΙΚ|ΚΑΣΤ|ΚΟΠ|ΛΙΧ|ΛΟΥΘΗΡ|ΜΑΙΝΤ|ΜΕΛ|ΣΙΓ|ΣΠ|ΣΤΕΓ|ΤΡΑΓ|ΤΣΑΓ|Φ|ΕΡ|ΑΔΑΠ|ΑΘΙΓΓ|ΑΜΗΧ|ΑΝΙΚ|ΑΝΟΡΓ|ΑΠΗΓ|ΑΠΙΘ|ΑΤΣΙΓΓ|ΒΑΣ|ΒΑΣΚ|ΒΑΘΥΓΑΛ|ΒΙΟΜΗΧ|ΒΡΑΧΥΚ|ΔΙΑΤ|ΔΙΑΦ|ΕΝΟΡΓ|ΘΥΣ|ΚΑΠΝΟΒΙΟΜΗΧ|ΚΑΤΑΓΑΛ|ΚΛΙΒ|ΚΟΙΛΑΡΦ|ΛΙΒ|ΜΕΓΛΟΒΙΟΜΗΧ|ΜΙΚΡΟΒΙΟΜΗΧ|ΝΤΑΒ|ΞΗΡΟΚΛΙΒ|ΟΛΙΓΟΔΑΜ|ΟΛΟΓΑΛ|ΠΕΝΤΑΡΦ|ΠΕΡΗΦ|ΠΕΡΙΤΡ|ΠΛΑΤ|ΠΟΛΥΔΑΠ|ΠΟΛΥΜΗΧ|ΣΤΕΦ|ΤΑΒ|ΤΕΤ|ΥΠΕΡΗΦ|ΥΠΟΚΟΠ|ΧΑΜΗΛΟΔΑΠ|ΨΗΛΟΤΑΒ)$/;
if((re2.test(w)) || (exept7.test(w))) {
w = w + "ΑΝ";
}
}
re3 = /^(.+?)(ΕΤΕ)$/;
re4 = /^(.+?)(ΗΣΕΤΕ)$/;
if(re4.test(w)) {
var fp = re4.exec(w);
stem = fp[1];
w = stem;
test1 = false;
}
if(re3.test(w)) {
var fp = re3.exec(w);
stem = fp[1];
w = stem;
test1 = false;
re3 = new RegExp(v2 + "$");
exept8 = /(ΟΔ|ΑΙΡ|ΦΟΡ|ΤΑΘ|ΔΙΑΘ|ΣΧ|ΕΝΔ|ΕΥΡ|ΤΙΘ|ΥΠΕΡΘ|ΡΑΘ|ΕΝΘ|ΡΟΘ|ΣΘ|ΠΥΡ|ΑΙΝ|ΣΥΝΔ|ΣΥΝ|ΣΥΝΘ|ΧΩΡ|ΠΟΝ|ΒΡ|ΚΑΘ|ΕΥΘ|ΕΚΘ|ΝΕΤ|ΡΟΝ|ΑΡΚ|ΒΑΡ|ΒΟΛ|ΩΦΕΛ)$/;
exept9 = /^(ΑΒΑΡ|ΒΕΝ|ΕΝΑΡ|ΑΒΡ|ΑΔ|ΑΘ|ΑΝ|ΑΠΛ|ΒΑΡΟΝ|ΝΤΡ|ΣΚ|ΚΟΠ|ΜΠΟΡ|ΝΙΦ|ΠΑΓ|ΠΑΡΑΚΑΛ|ΣΕΡΠ|ΣΚΕΛ|ΣΥΡΦ|ΤΟΚ|Υ|Δ|ΕΜ|ΘΑΡΡ|Θ)$/;
if((re3.test(w)) || (exept8.test(w)) || (exept9.test(w))) {
w = w + "ΕΤ";
}
}
re = /^(.+?)(ΟΝΤΑΣ|ΩΝΤΑΣ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept10 = /^(ΑΡΧ)$/;
exept11 = /(ΚΡΕ)$/;
if(exept10.test(w)) {
w = w + "ΟΝΤ";
}
if(exept11.test(w)) {
w = w + "ΩΝΤ";
}
}
re = /^(.+?)(ΟΜΑΣΤΕ|ΙΟΜΑΣΤΕ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept11 = /^(ΟΝ)$/;
if(exept11.test(w)) {
w = w + "ΟΜΑΣΤ";
}
}
re = /^(.+?)(ΕΣΤΕ)$/;
re2 = /^(.+?)(ΙΕΣΤΕ)$/;
if(re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
w = stem;
test1 = false;
re2 = /^(Π|ΑΠ|ΣΥΜΠ|ΑΣΥΜΠ|ΑΚΑΤΑΠ|ΑΜΕΤΑΜΦ)$/;
if(re2.test(w)) {
w = w + "ΙΕΣΤ";
}
}
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept12 = /^(ΑΛ|ΑΡ|ΕΚΤΕΛ|Ζ|Μ|Ξ|ΠΑΡΑΚΑΛ|ΑΡ|ΠΡΟ|ΝΙΣ)$/;
if(exept12.test(w)) {
w = w + "ΕΣΤ";
}
}
re = /^(.+?)(ΗΚΑ|ΗΚΕΣ|ΗΚΕ)$/;
re2 = /^(.+?)(ΗΘΗΚΑ|ΗΘΗΚΕΣ|ΗΘΗΚΕ)$/;
if(re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
w = stem;
test1 = false;
}
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept13 = /(ΣΚΩΛ|ΣΚΟΥΛ|ΝΑΡΘ|ΣΦ|ΟΘ|ΠΙΘ)$/;
exept14 = /^(ΔΙΑΘ|Θ|ΠΑΡΑΚΑΤΑΘ|ΠΡΟΣΘ|ΣΥΝΘ|)$/;
if((exept13.test(w)) || (exept14.test(w))) {
w = w + "ΗΚ";
}
}
re = /^(.+?)(ΟΥΣΑ|ΟΥΣΕΣ|ΟΥΣΕ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept15 = /^(ΦΑΡΜΑΚ|ΧΑΔ|ΑΓΚ|ΑΝΑΡΡ|ΒΡΟΜ|ΕΚΛΙΠ|ΛΑΜΠΙΔ|ΛΕΧ|Μ|ΠΑΤ|Ρ|Λ|ΜΕΔ|ΜΕΣΑΖ|ΥΠΟΤΕΙΝ|ΑΜ|ΑΙΘ|ΑΝΗΚ|ΔΕΣΠΟΖ|ΕΝΔΙΑΦΕΡ|ΔΕ|ΔΕΥΤΕΡΕΥ|ΚΑΘΑΡΕΥ|ΠΛΕ|ΤΣΑ)$/;
exept16 = /(ΠΟΔΑΡ|ΒΛΕΠ|ΠΑΝΤΑΧ|ΦΡΥΔ|ΜΑΝΤΙΛ|ΜΑΛΛ|ΚΥΜΑΤ|ΛΑΧ|ΛΗΓ|ΦΑΓ|ΟΜ|ΠΡΩΤ)$/;
if((exept15.test(w)) || (exept16.test(w))) {
w = w + "ΟΥΣ";
}
}
re = /^(.+?)(ΑΓΑ|ΑΓΕΣ|ΑΓΕ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept17 = /^(ΨΟΦ|ΝΑΥΛΟΧ)$/;
exept20 = /(ΚΟΛΛ)$/;
exept18 = /^(ΑΒΑΣΤ|ΠΟΛΥΦ|ΑΔΗΦ|ΠΑΜΦ|Ρ|ΑΣΠ|ΑΦ|ΑΜΑΛ|ΑΜΑΛΛΙ|ΑΝΥΣΤ|ΑΠΕΡ|ΑΣΠΑΡ|ΑΧΑΡ|ΔΕΡΒΕΝ|ΔΡΟΣΟΠ|ΞΕΦ|ΝΕΟΠ|ΝΟΜΟΤ|ΟΛΟΠ|ΟΜΟΤ|ΠΡΟΣΤ|ΠΡΟΣΩΠΟΠ|ΣΥΜΠ|ΣΥΝΤ|Τ|ΥΠΟΤ|ΧΑΡ|ΑΕΙΠ|ΑΙΜΟΣΤ|ΑΝΥΠ|ΑΠΟΤ|ΑΡΤΙΠ|ΔΙΑΤ|ΕΝ|ΕΠΙΤ|ΚΡΟΚΑΛΟΠ|ΣΙΔΗΡΟΠ|Λ|ΝΑΥ|ΟΥΛΑΜ|ΟΥΡ|Π|ΤΡ|Μ)$/;
exept19 = /(ΟΦ|ΠΕΛ|ΧΟΡΤ|ΛΛ|ΣΦ|ΡΠ|ΦΡ|ΠΡ|ΛΟΧ|ΣΜΗΝ)$/;
if(((exept18.test(w)) || (exept19.test(w))) && !((exept17.test(w)) || (exept20.test(w)))) {
w = w + "ΑΓ";
}
}
re = /^(.+?)(ΗΣΕ|ΗΣΟΥ|ΗΣΑ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept21 = /^(Ν|ΧΕΡΣΟΝ|ΔΩΔΕΚΑΝ|ΕΡΗΜΟΝ|ΜΕΓΑΛΟΝ|ΕΠΤΑΝ)$/;
if(exept21.test(w)) {
w = w + "ΗΣ";
}
}
re = /^(.+?)(ΗΣΤΕ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept22 = /^(ΑΣΒ|ΣΒ|ΑΧΡ|ΧΡ|ΑΠΛ|ΑΕΙΜΝ|ΔΥΣΧΡ|ΕΥΧΡ|ΚΟΙΝΟΧΡ|ΠΑΛΙΜΨ)$/;
if(exept22.test(w)) {
w = w + "ΗΣΤ";
}
}
re = /^(.+?)(ΟΥΝΕ|ΗΣΟΥΝΕ|ΗΘΟΥΝΕ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept23 = /^(Ν|Ρ|ΣΠΙ|ΣΤΡΑΒΟΜΟΥΤΣ|ΚΑΚΟΜΟΥΤΣ|ΕΞΩΝ)$/;
if(exept23.test(w)) {
w = w + "ΟΥΝ";
}
}
re = /^(.+?)(ΟΥΜΕ|ΗΣΟΥΜΕ|ΗΘΟΥΜΕ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
test1 = false;
exept24 = /^(ΠΑΡΑΣΟΥΣ|Φ|Χ|ΩΡΙΟΠΛ|ΑΖ|ΑΛΛΟΣΟΥΣ|ΑΣΟΥΣ)$/;
if(exept24.test(w)) {
w = w + "ΟΥΜ";
}
}
re = /^(.+?)(ΜΑΤΑ|ΜΑΤΩΝ|ΜΑΤΟΣ)$/;
re2 = /^(.+?)(Α|ΑΓΑΤΕ|ΑΓΑΝ|ΑΕΙ|ΑΜΑΙ|ΑΝ|ΑΣ|ΑΣΑΙ|ΑΤΑΙ|ΑΩ|Ε|ΕΙ|ΕΙΣ|ΕΙΤΕ|ΕΣΑΙ|ΕΣ|ΕΤΑΙ|Ι|ΙΕΜΑΙ|ΙΕΜΑΣΤΕ|ΙΕΤΑΙ|ΙΕΣΑΙ|ΙΕΣΑΣΤΕ|ΙΟΜΑΣΤΑΝ|ΙΟΜΟΥΝ|ΙΟΜΟΥΝΑ|ΙΟΝΤΑΝ|ΙΟΝΤΟΥΣΑΝ|ΙΟΣΑΣΤΑΝ|ΙΟΣΑΣΤΕ|ΙΟΣΟΥΝ|ΙΟΣΟΥΝΑ|ΙΟΤΑΝ|ΙΟΥΜΑ|ΙΟΥΜΑΣΤΕ|ΙΟΥΝΤΑΙ|ΙΟΥΝΤΑΝ|Η|ΗΔΕΣ|ΗΔΩΝ|ΗΘΕΙ|ΗΘΕΙΣ|ΗΘΕΙΤΕ|ΗΘΗΚΑΤΕ|ΗΘΗΚΑΝ|ΗΘΟΥΝ|ΗΘΩ|ΗΚΑΤΕ|ΗΚΑΝ|ΗΣ|ΗΣΑΝ|ΗΣΑΤΕ|ΗΣΕΙ|ΗΣΕΣ|ΗΣΟΥΝ|ΗΣΩ|Ο|ΟΙ|ΟΜΑΙ|ΟΜΑΣΤΑΝ|ΟΜΟΥΝ|ΟΜΟΥΝΑ|ΟΝΤΑΙ|ΟΝΤΑΝ|ΟΝΤΟΥΣΑΝ|ΟΣ|ΟΣΑΣΤΑΝ|ΟΣΑΣΤΕ|ΟΣΟΥΝ|ΟΣΟΥΝΑ|ΟΤΑΝ|ΟΥ|ΟΥΜΑΙ|ΟΥΜΑΣΤΕ|ΟΥΝ|ΟΥΝΤΑΙ|ΟΥΝΤΑΝ|ΟΥΣ|ΟΥΣΑΝ|ΟΥΣΑΤΕ|Υ|ΥΣ|Ω|ΩΝ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem + "ΜΑ";
}
if((re2.test(w)) && (test1)) {
var fp = re2.exec(w);
stem = fp[1];
w = stem;
}
re = /^(.+?)(ΕΣΤΕΡ|ΕΣΤΑΤ|ΟΤΕΡ|ΟΤΑΤ|ΥΤΕΡ|ΥΤΑΤ|ΩΤΕΡ|ΩΤΑΤ)$/;
if(re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
w = stem;
}
return w;
};
var greekStemmer = function (token) {
return token.update(function (word) {
return stemWord(word);
})
}
var idx = lunr(function () {
this.field('title')
this.field('excerpt')
this.field('categories')
this.field('tags')
this.ref('id')
this.pipeline.remove(lunr.trimmer)
this.pipeline.add(greekStemmer)
this.pipeline.remove(lunr.stemmer)
for (var item in store) {
this.add({
title: store[item].title,
excerpt: store[item].excerpt,
categories: store[item].categories,
tags: store[item].tags,
id: item
})
}
});
$(document).ready(function() {
$('input#search').on('keyup', function () {
var resultdiv = $('#results');
var query = $(this).val().toLowerCase();
var result =
idx.query(function (q) {
query.split(lunr.tokenizer.separator).forEach(function (term) {
q.term(term, { boost: 100 })
if(query.lastIndexOf(" ") != query.length-1){
q.term(term, { usePipeline: false, wildcard: lunr.Query.wildcard.TRAILING, boost: 10 })
}
if (term != ""){
q.term(term, { usePipeline: false, editDistance: 1, boost: 1 })
}
})
});
resultdiv.empty();
resultdiv.prepend('<p class="results__found">'+result.length+' Result(s) found</p>');
for (var item in result) {
var ref = result[item].ref;
if(store[ref].teaser){
var searchitem =
'<div class="list__item">'+
'<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">'+
'<h2 class="archive__item-title" itemprop="headline">'+
'<a href="'+store[ref].url+'" rel="permalink">'+store[ref].title+'</a>'+
'</h2>'+
'<div class="archive__item-teaser">'+
'<img src="'+store[ref].teaser+'" alt="">'+
'</div>'+
'<p class="archive__item-excerpt" itemprop="description">'+store[ref].excerpt.split(" ").splice(0,20).join(" ")+'...</p>'+
'</article>'+
'</div>';
}
else{
var searchitem =
'<div class="list__item">'+
'<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">'+
'<h2 class="archive__item-title" itemprop="headline">'+
'<a href="'+store[ref].url+'" rel="permalink">'+store[ref].title+'</a>'+
'</h2>'+
'<p class="archive__item-excerpt" itemprop="description">'+store[ref].excerpt.split(" ").splice(0,20).join(" ")+'...</p>'+
'</article>'+
'</div>';
}
resultdiv.append(searchitem);
}
});
});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

6
assets/js/lunr/lunr.min.js vendored 100644

File diff suppressed because one or more lines are too long

6
assets/js/main.min.js vendored 100644

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,484 @@
/*!
* gumshoejs v5.1.1
* A simple, framework-agnostic scrollspy script.
* (c) 2019 Chris Ferdinandi
* MIT License
* http://github.com/cferdinandi/gumshoe
*/
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define([], (function () {
return factory(root);
}));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.Gumshoe = factory(root);
}
})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, (function (window) {
'use strict';
//
// Defaults
//
var defaults = {
// Active classes
navClass: 'active',
contentClass: 'active',
// Nested navigation
nested: false,
nestedClass: 'active',
// Offset & reflow
offset: 0,
reflow: false,
// Event support
events: true
};
//
// Methods
//
/**
* Merge two or more objects together.
* @param {Object} objects The objects to merge together
* @returns {Object} Merged values of defaults and options
*/
var extend = function () {
var merged = {};
Array.prototype.forEach.call(arguments, (function (obj) {
for (var key in obj) {
if (!obj.hasOwnProperty(key)) return;
merged[key] = obj[key];
}
}));
return merged;
};
/**
* Emit a custom event
* @param {String} type The event type
* @param {Node} elem The element to attach the event to
* @param {Object} detail Any details to pass along with the event
*/
var emitEvent = function (type, elem, detail) {
// Make sure events are enabled
if (!detail.settings.events) return;
// Create a new event
var event = new CustomEvent(type, {
bubbles: true,
cancelable: true,
detail: detail
});
// Dispatch the event
elem.dispatchEvent(event);
};
/**
* Get an element's distance from the top of the Document.
* @param {Node} elem The element
* @return {Number} Distance from the top in pixels
*/
var getOffsetTop = function (elem) {
var location = 0;
if (elem.offsetParent) {
while (elem) {
location += elem.offsetTop;
elem = elem.offsetParent;
}
}
return location >= 0 ? location : 0;
};
/**
* Sort content from first to last in the DOM
* @param {Array} contents The content areas
*/
var sortContents = function (contents) {
if(contents) {
contents.sort((function (item1, item2) {
var offset1 = getOffsetTop(item1.content);
var offset2 = getOffsetTop(item2.content);
if (offset1 < offset2) return -1;
return 1;
}));
}
};
/**
* Get the offset to use for calculating position
* @param {Object} settings The settings for this instantiation
* @return {Float} The number of pixels to offset the calculations
*/
var getOffset = function (settings) {
// if the offset is a function run it
if (typeof settings.offset === 'function') {
return parseFloat(settings.offset());
}
// Otherwise, return it as-is
return parseFloat(settings.offset);
};
/**
* Get the document element's height
* @private
* @returns {Number}
*/
var getDocumentHeight = function () {
return Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
};
/**
* Determine if an element is in view
* @param {Node} elem The element
* @param {Object} settings The settings for this instantiation
* @param {Boolean} bottom If true, check if element is above bottom of viewport instead
* @return {Boolean} Returns true if element is in the viewport
*/
var isInView = function (elem, settings, bottom) {
var bounds = elem.getBoundingClientRect();
var offset = getOffset(settings);
if (bottom) {
return parseInt(bounds.bottom, 10) < (window.innerHeight || document.documentElement.clientHeight);
}
return parseInt(bounds.top, 10) <= offset;
};
/**
* Check if at the bottom of the viewport
* @return {Boolean} If true, page is at the bottom of the viewport
*/
var isAtBottom = function () {
if (window.innerHeight + window.pageYOffset >= getDocumentHeight()) return true;
return false;
};
/**
* Check if the last item should be used (even if not at the top of the page)
* @param {Object} item The last item
* @param {Object} settings The settings for this instantiation
* @return {Boolean} If true, use the last item
*/
var useLastItem = function (item, settings) {
if (isAtBottom() && isInView(item.content, settings, true)) return true;
return false;
};
/**
* Get the active content
* @param {Array} contents The content areas
* @param {Object} settings The settings for this instantiation
* @return {Object} The content area and matching navigation link
*/
var getActive = function (contents, settings) {
var last = contents[contents.length-1];
if (useLastItem(last, settings)) return last;
for (var i = contents.length - 1; i >= 0; i--) {
if (isInView(contents[i].content, settings)) return contents[i];
}
};
/**
* Deactivate parent navs in a nested navigation
* @param {Node} nav The starting navigation element
* @param {Object} settings The settings for this instantiation
*/
var deactivateNested = function (nav, settings) {
// If nesting isn't activated, bail
if (!settings.nested) return;
// Get the parent navigation
var li = nav.parentNode.closest('li');
if (!li) return;
// Remove the active class
li.classList.remove(settings.nestedClass);
// Apply recursively to any parent navigation elements
deactivateNested(li, settings);
};
/**
* Deactivate a nav and content area
* @param {Object} items The nav item and content to deactivate
* @param {Object} settings The settings for this instantiation
*/
var deactivate = function (items, settings) {
// Make sure their are items to deactivate
if (!items) return;
// Get the parent list item
var li = items.nav.closest('li');
if (!li) return;
// Remove the active class from the nav and content
li.classList.remove(settings.navClass);
items.content.classList.remove(settings.contentClass);
// Deactivate any parent navs in a nested navigation
deactivateNested(li, settings);
// Emit a custom event
emitEvent('gumshoeDeactivate', li, {
link: items.nav,
content: items.content,
settings: settings
});
};
/**
* Activate parent navs in a nested navigation
* @param {Node} nav The starting navigation element
* @param {Object} settings The settings for this instantiation
*/
var activateNested = function (nav, settings) {
// If nesting isn't activated, bail
if (!settings.nested) return;
// Get the parent navigation
var li = nav.parentNode.closest('li');
if (!li) return;
// Add the active class
li.classList.add(settings.nestedClass);
// Apply recursively to any parent navigation elements
activateNested(li, settings);
};
/**
* Activate a nav and content area
* @param {Object} items The nav item and content to activate
* @param {Object} settings The settings for this instantiation
*/
var activate = function (items, settings) {
// Make sure their are items to activate
if (!items) return;
// Get the parent list item
var li = items.nav.closest('li');
if (!li) return;
// Add the active class to the nav and content
li.classList.add(settings.navClass);
items.content.classList.add(settings.contentClass);
// Activate any parent navs in a nested navigation
activateNested(li, settings);
// Emit a custom event
emitEvent('gumshoeActivate', li, {
link: items.nav,
content: items.content,
settings: settings
});
};
/**
* Create the Constructor object
* @param {String} selector The selector to use for navigation items
* @param {Object} options User options and settings
*/
var Constructor = function (selector, options) {
//
// Variables
//
var publicAPIs = {};
var navItems, contents, current, timeout, settings;
//
// Methods
//
/**
* Set variables from DOM elements
*/
publicAPIs.setup = function () {
// Get all nav items
navItems = document.querySelectorAll(selector);
// Create contents array
contents = [];
// Loop through each item, get it's matching content, and push to the array
Array.prototype.forEach.call(navItems, (function (item) {
// Get the content for the nav item
var content = document.getElementById(decodeURIComponent(item.hash.substr(1)));
if (!content) return;
// Push to the contents array
contents.push({
nav: item,
content: content
});
}));
// Sort contents by the order they appear in the DOM
sortContents(contents);
};
/**
* Detect which content is currently active
*/
publicAPIs.detect = function () {
// Get the active content
var active = getActive(contents, settings);
// if there's no active content, deactivate and bail
if (!active) {
if (current) {
deactivate(current, settings);
current = null;
}
return;
}
// If the active content is the one currently active, do nothing
if (current && active.content === current.content) return;
// Deactivate the current content and activate the new content
deactivate(current, settings);
activate(active, settings);
// Update the currently active content
current = active;
};
/**
* Detect the active content on scroll
* Debounced for performance
*/
var scrollHandler = function (event) {
// If there's a timer, cancel it
if (timeout) {
window.cancelAnimationFrame(timeout);
}
// Setup debounce callback
timeout = window.requestAnimationFrame(publicAPIs.detect);
};
/**
* Update content sorting on resize
* Debounced for performance
*/
var resizeHandler = function (event) {
// If there's a timer, cancel it
if (timeout) {
window.cancelAnimationFrame(timeout);
}
// Setup debounce callback
timeout = window.requestAnimationFrame((function () {
sortContents(contents);
publicAPIs.detect();
}));
};
/**
* Destroy the current instantiation
*/
publicAPIs.destroy = function () {
// Undo DOM changes
if (current) {
deactivate(current, settings);
}
// Remove event listeners
window.removeEventListener('scroll', scrollHandler, false);
if (settings.reflow) {
window.removeEventListener('resize', resizeHandler, false);
}
// Reset variables
contents = null;
navItems = null;
current = null;
timeout = null;
settings = null;
};
/**
* Initialize the current instantiation
*/
var init = function () {
// Merge user options into defaults
settings = extend(defaults, options || {});
// Setup variables based on the current DOM
publicAPIs.setup();
// Find the currently active content
publicAPIs.detect();
// Setup event listeners
window.addEventListener('scroll', scrollHandler, false);
if (settings.reflow) {
window.addEventListener('resize', resizeHandler, false);
}
};
//
// Initialize and return the public APIs
//
init();
return publicAPIs;
};
//
// Return the Constructor
//
return Constructor;
}));

View File

@ -0,0 +1,252 @@
/*!
* jQuery throttle / debounce - v1.1 - 3/7/2010
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
// Script: jQuery throttle / debounce: Sometimes, less is more!
//
// *Version: 1.1, Last updated: 3/7/2010*
//
// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
// GitHub - http://github.com/cowboy/jquery-throttle-debounce/
// Source - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
// (Minified) - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
//
// About: License
//
// Copyright (c) 2010 "Cowboy" Ben Alman,
// Dual licensed under the MIT and GPL licenses.
// http://benalman.com/about/license/
//
// About: Examples
//
// These working examples, complete with fully commented code, illustrate a few
// ways in which this plugin can be used.
//
// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
//
// About: Support and Testing
//
// Information about what version or versions of jQuery this plugin has been
// tested with, what browsers it has been tested in, and where the unit tests
// reside (so you can test it yourself).
//
// jQuery Versions - none, 1.3.2, 1.4.2
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
// Unit Tests - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
//
// About: Release History
//
// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
// executed later than they should. Reworked a fair amount of internal
// logic as well.
// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
// from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
// no_trailing throttle parameter and debounce functionality.
//
// Topic: Note for non-jQuery users
//
// jQuery isn't actually required for this plugin, because nothing internal
// uses any jQuery methods or properties. jQuery is just used as a namespace
// under which these methods can exist.
//
// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
// when this plugin is loaded, the method described below will be created in
// the `Cowboy` namespace. Usage will be exactly the same, but instead of
// $.method() or jQuery.method(), you'll need to use Cowboy.method().
(function(window,undefined){
'$:nomunge'; // Used by YUI compressor.
// Since jQuery really isn't required for this plugin, use `jQuery` as the
// namespace only if it already exists, otherwise use the `Cowboy` namespace,
// creating it if necessary.
var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
// Internal method reference.
jq_throttle;
// Method: jQuery.throttle
//
// Throttle execution of a function. Especially useful for rate limiting
// execution of handlers on events like resize and scroll. If you want to
// rate-limit execution of a function to a single time, see the
// <jQuery.debounce> method.
//
// In this visualization, | is a throttled-function call and X is the actual
// callback execution:
//
// > Throttled with `no_trailing` specified as false or unspecified:
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
// > X X X X X X X X X X X X
// >
// > Throttled with `no_trailing` specified as true:
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
// > X X X X X X X X X X
//
// Usage:
//
// > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
// >
// > jQuery('selector').bind( 'someevent', throttled );
// > jQuery('selector').unbind( 'someevent', throttled );
//
// This also works in jQuery 1.4+:
//
// > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
// > jQuery('selector').unbind( 'someevent', callback );
//
// Arguments:
//
// delay - (Number) A zero-or-greater delay in milliseconds. For event
// callbacks, values around 100 or 250 (or even higher) are most useful.
// no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
// true, callback will only execute every `delay` milliseconds while the
// throttled-function is being called. If no_trailing is false or
// unspecified, callback will be executed one final time after the last
// throttled-function call. (After the throttled-function has not been
// called for `delay` milliseconds, the internal counter is reset)
// callback - (Function) A function to be executed after delay milliseconds.
// The `this` context and all arguments are passed through, as-is, to
// `callback` when the throttled-function is executed.
//
// Returns:
//
// (Function) A new, throttled, function.
$.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
// After wrapper has stopped being called, this timeout ensures that
// `callback` is executed at the proper times in `throttle` and `end`
// debounce modes.
var timeout_id,
// Keep track of the last time `callback` was executed.
last_exec = 0;
// `no_trailing` defaults to falsy.
if ( typeof no_trailing !== 'boolean' ) {
debounce_mode = callback;
callback = no_trailing;
no_trailing = undefined;
}
// The `wrapper` function encapsulates all of the throttling / debouncing
// functionality and when executed will limit the rate at which `callback`
// is executed.
function wrapper() {
var that = this,
elapsed = +new Date() - last_exec,
args = arguments;
// Execute `callback` and update the `last_exec` timestamp.
function exec() {
last_exec = +new Date();
callback.apply( that, args );
};
// If `debounce_mode` is true (at_begin) this is used to clear the flag
// to allow future `callback` executions.
function clear() {
timeout_id = undefined;
};
if ( debounce_mode && !timeout_id ) {
// Since `wrapper` is being called for the first time and
// `debounce_mode` is true (at_begin), execute `callback`.
exec();
}
// Clear any existing timeout.
timeout_id && clearTimeout( timeout_id );
if ( debounce_mode === undefined && elapsed > delay ) {
// In throttle mode, if `delay` time has been exceeded, execute
// `callback`.
exec();
} else if ( no_trailing !== true ) {
// In trailing throttle mode, since `delay` time has not been
// exceeded, schedule `callback` to execute `delay` ms after most
// recent execution.
//
// If `debounce_mode` is true (at_begin), schedule `clear` to execute
// after `delay` ms.
//
// If `debounce_mode` is false (at end), schedule `callback` to
// execute after `delay` ms.
timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
}
};
// Set the guid of `wrapper` function to the same of original callback, so
// it can be removed in jQuery 1.4+ .unbind or .die by using the original
// callback as a reference.
if ( $.guid ) {
wrapper.guid = callback.guid = callback.guid || $.guid++;
}
// Return the wrapper function.
return wrapper;
};
// Method: jQuery.debounce
//
// Debounce execution of a function. Debouncing, unlike throttling,
// guarantees that a function is only executed a single time, either at the
// very beginning of a series of calls, or at the very end. If you want to
// simply rate-limit execution of a function, see the <jQuery.throttle>
// method.
//
// In this visualization, | is a debounced-function call and X is the actual
// callback execution:
//
// > Debounced with `at_begin` specified as false or unspecified:
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
// > X X
// >
// > Debounced with `at_begin` specified as true:
// > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
// > X X
//
// Usage:
//
// > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
// >
// > jQuery('selector').bind( 'someevent', debounced );
// > jQuery('selector').unbind( 'someevent', debounced );
//
// This also works in jQuery 1.4+:
//
// > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
// > jQuery('selector').unbind( 'someevent', callback );
//
// Arguments:
//
// delay - (Number) A zero-or-greater delay in milliseconds. For event
// callbacks, values around 100 or 250 (or even higher) are most useful.
// at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
// unspecified, callback will only be executed `delay` milliseconds after
// the last debounced-function call. If at_begin is true, callback will be
// executed only at the first debounced-function call. (After the
// throttled-function has not been called for `delay` milliseconds, the
// internal counter is reset)
// callback - (Function) A function to be executed after delay milliseconds.
// The `this` context and all arguments are passed through, as-is, to
// `callback` when the debounced-function is executed.
//
// Returns:
//
// (Function) A new, debounced, function.
$.debounce = function( delay, at_begin, callback ) {
return callback === undefined
? jq_throttle( delay, at_begin, false )
: jq_throttle( delay, callback, at_begin !== false );
};
})(this);

View File

@ -0,0 +1,82 @@
/*jshint browser:true */
/*!
* FitVids 1.1
*
* Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
* Released under the WTFPL license - http://sam.zoy.org/wtfpl/
*
*/
;(function( $ ){
'use strict';
$.fn.fitVids = function( options ) {
var settings = {
customSelector: null,
ignore: null
};
if(!document.getElementById('fit-vids-style')) {
// appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js
var head = document.head || document.getElementsByTagName('head')[0];
var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}';
var div = document.createElement("div");
div.innerHTML = '<p>x</p><style id="fit-vids-style">' + css + '</style>';
head.appendChild(div.childNodes[1]);
}
if ( options ) {
$.extend( settings, options );
}
return this.each(function(){
var selectors = [
'iframe[src*="player.vimeo.com"]',
'iframe[src*="youtube.com"]',
'iframe[src*="youtube-nocookie.com"]',
'iframe[src*="kickstarter.com"][src*="video.html"]',
'object',
'embed'
];
if (settings.customSelector) {
selectors.push(settings.customSelector);
}
var ignoreList = '.fitvidsignore';
if(settings.ignore) {
ignoreList = ignoreList + ', ' + settings.ignore;
}
var $allVideos = $(this).find(selectors.join(','));
$allVideos = $allVideos.not('object object'); // SwfObj conflict patch
$allVideos = $allVideos.not(ignoreList); // Disable FitVids on this video.
$allVideos.each(function(count){
var $this = $(this);
if($this.parents(ignoreList).length > 0) {
return; // Disable FitVids on this video.
}
if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
if ((!$this.css('height') && !$this.css('width')) && (isNaN($this.attr('height')) || isNaN($this.attr('width'))))
{
$this.attr('height', 9);
$this.attr('width', 16);
}
var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
aspectRatio = height / width;
if(!$this.attr('id')){
var videoID = 'fitvid' + count;
$this.attr('id', videoID);
}
$this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+'%');
$this.removeAttr('height').removeAttr('width');
});
});
};
// Works with either jQuery or Zepto
})( window.jQuery || window.Zepto );

View File

@ -0,0 +1,127 @@
/*
GreedyNav.js - http://lukejacksonn.com/actuate
Licensed under the MIT license - http://opensource.org/licenses/MIT
Copyright (c) 2015 Luke Jackson
*/
$(function() {
var $btn = $("nav.greedy-nav .greedy-nav__toggle");
var $vlinks = $("nav.greedy-nav .visible-links");
var $hlinks = $("nav.greedy-nav .hidden-links");
var $nav = $("nav.greedy-nav");
var $logo = $('nav.greedy-nav .site-logo');
var $logoImg = $('nav.greedy-nav .site-logo img');
var $title = $("nav.greedy-nav .site-title");
var $search = $('nav.greedy-nav button.search__toggle');
var numOfItems, totalSpace, closingTime, breakWidths;
// This function measures both hidden and visible links and sets the navbar breakpoints
// This is called the first time the script runs and everytime the "check()" function detects a change of window width that reached a different CSS width breakpoint, which affects the size of navbar Items
// Please note that "CSS width breakpoints" (which are only 4) !== "navbar breakpoints" (which are as many as the number of items on the navbar)
function measureLinks(){
numOfItems = 0;
totalSpace = 0;
closingTime = 1000;
breakWidths = [];
// Adds the width of a navItem in order to create breakpoints for the navbar
function addWidth(i, w) {
totalSpace += w;
numOfItems += 1;
breakWidths.push(totalSpace);
}
// Measures the width of hidden links by making a temporary clone of them and positioning under visible links
function hiddenWidth(obj){
var clone = obj.clone();
clone.css("visibility","hidden");
$vlinks.append(clone);
addWidth(0, clone.outerWidth());
clone.remove();
}
// Measure both visible and hidden links widths
$vlinks.children().outerWidth(addWidth);
$hlinks.children().each(function(){hiddenWidth($(this))});
}
// Get initial state
measureLinks();
var winWidth = $( window ).width();
// Set the last measured CSS width breakpoint: 0: <768px, 1: <1024px, 2: < 1280px, 3: >= 1280px.
var lastBreakpoint = winWidth < 768 ? 0 : winWidth < 1024 ? 1 : winWidth < 1280 ? 2 : 3;
var availableSpace, numOfVisibleItems, requiredSpace, timer;
function check() {
winWidth = $( window ).width();
// Set the current CSS width breakpoint: 0: <768px, 1: <1024px, 2: < 1280px, 3: >= 1280px.
var curBreakpoint = winWidth < 768 ? 0 : winWidth < 1024 ? 1 : winWidth < 1280 ? 2 : 3;
// If current breakpoint is different from last measured breakpoint, measureLinks again
if(curBreakpoint !== lastBreakpoint) measureLinks();
// Set the last measured CSS width breakpoint with the current breakpoint
lastBreakpoint = curBreakpoint;
// Get instant state
numOfVisibleItems = $vlinks.children().length;
// Decrease the width of visible elements from the nav innerWidth to find out the available space for navItems
availableSpace = /* nav */ $nav.innerWidth()
- /* logo */ ($logo.length !== 0 ? $logo.outerWidth(true) : 0)
- /* title */ $title.outerWidth(true)
- /* search */ ($search.length !== 0 ? $search.outerWidth(true) : 0)
- /* toggle */ (numOfVisibleItems !== breakWidths.length ? $btn.outerWidth(true) : 0);
requiredSpace = breakWidths[numOfVisibleItems - 1];
// There is not enought space
if (requiredSpace > availableSpace) {
$vlinks.children().last().prependTo($hlinks);
numOfVisibleItems -= 1;
check();
// There is more than enough space. If only one element is hidden, add the toggle width to the available space
} else if (availableSpace + (numOfVisibleItems === breakWidths.length - 1?$btn.outerWidth(true):0) > breakWidths[numOfVisibleItems]) {
$hlinks.children().first().appendTo($vlinks);
numOfVisibleItems += 1;
check();
}
// Update the button accordingly
$btn.attr("count", numOfItems - numOfVisibleItems);
if (numOfVisibleItems === numOfItems) {
$btn.addClass('hidden');
} else $btn.removeClass('hidden');
}
// Window listeners
$(window).resize(function() {
check();
});
$btn.on('click', function() {
$hlinks.toggleClass('hidden');
$(this).toggleClass('close');
clearTimeout(timer);
});
$hlinks.on('mouseleave', function() {
// Mouse has left, start the timer
timer = setTimeout(function() {
$hlinks.addClass('hidden');
}, closingTime);
}).on('mouseenter', function() {
// Mouse is back, cancel the timer
clearTimeout(timer);
})
// check if page has a logo
if($logoImg.length !== 0){
// check if logo is not loaded
if(!($logoImg[0].complete || $logoImg[0].naturalWidth !== 0)){
// if logo is not loaded wait for logo to load or fail to check
$logoImg.one("load error", check);
// if logo is already loaded just check
} else check();
// if page does not have a logo just check
} else check();
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,650 @@
/*!
* smooth-scroll v16.1.2
* Animate scrolling to anchor links
* (c) 2020 Chris Ferdinandi
* MIT License
* http://github.com/cferdinandi/smooth-scroll
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], (function () {
return factory(root);
}));
} else if (typeof exports === 'object') {
module.exports = factory(root);
} else {
root.SmoothScroll = factory(root);
}
})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, (function (window) {
'use strict';
//
// Default settings
//
var defaults = {
// Selectors
ignore: '[data-scroll-ignore]',
header: null,
topOnEmptyHash: true,
// Speed & Duration
speed: 500,
speedAsDuration: false,
durationMax: null,
durationMin: null,
clip: true,
offset: 0,
// Easing
easing: 'easeInOutCubic',
customEasing: null,
// History
updateURL: true,
popstate: true,
// Custom Events
emitEvents: true
};
//
// Utility Methods
//
/**
* Check if browser supports required methods
* @return {Boolean} Returns true if all required methods are supported
*/
var supports = function () {
return (
'querySelector' in document &&
'addEventListener' in window &&
'requestAnimationFrame' in window &&
'closest' in window.Element.prototype
);
};
/**
* Merge two or more objects together.
* @param {Object} objects The objects to merge together
* @returns {Object} Merged values of defaults and options
*/
var extend = function () {
var merged = {};
Array.prototype.forEach.call(arguments, (function (obj) {
for (var key in obj) {
if (!obj.hasOwnProperty(key)) return;
merged[key] = obj[key];
}
}));
return merged;
};
/**
* Check to see if user prefers reduced motion
* @param {Object} settings Script settings
*/
var reduceMotion = function () {
if ('matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches) {
return true;
}
return false;
};
/**
* Get the height of an element.
* @param {Node} elem The element to get the height of
* @return {Number} The element's height in pixels
*/
var getHeight = function (elem) {
return parseInt(window.getComputedStyle(elem).height, 10);
};
/**
* Escape special characters for use with querySelector
* @author Mathias Bynens
* @link https://github.com/mathiasbynens/CSS.escape
* @param {String} id The anchor ID to escape
*/
var escapeCharacters = function (id) {
// Remove leading hash
if (id.charAt(0) === '#') {
id = id.substr(1);
}
var string = String(id);
var length = string.length;
var index = -1;
var codeUnit;
var result = '';
var firstCodeUnit = string.charCodeAt(0);
while (++index < length) {
codeUnit = string.charCodeAt(index);
// Note: theres no need to special-case astral symbols, surrogate
// pairs, or lone surrogates.
// If the character is NULL (U+0000), then throw an
// `InvalidCharacterError` exception and terminate these steps.
if (codeUnit === 0x0000) {
throw new InvalidCharacterError(
'Invalid character: the input contains U+0000.'
);
}
if (
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
// U+007F, […]
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
// If the character is the first character and is in the range [0-9]
// (U+0030 to U+0039), […]
(index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
// If the character is the second character and is in the range [0-9]
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
(
index === 1 &&
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
firstCodeUnit === 0x002D
)
) {
// http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
result += '\\' + codeUnit.toString(16) + ' ';
continue;
}
// If the character is not handled by one of the above rules and is
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
// U+005A), or [a-z] (U+0061 to U+007A), […]
if (
codeUnit >= 0x0080 ||
codeUnit === 0x002D ||
codeUnit === 0x005F ||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
codeUnit >= 0x0061 && codeUnit <= 0x007A
) {
// the character itself
result += string.charAt(index);
continue;
}
// Otherwise, the escaped character.
// http://dev.w3.org/csswg/cssom/#escape-a-character
result += '\\' + string.charAt(index);
}
// Return sanitized hash
return '#' + result;
};
/**
* Calculate the easing pattern
* @link https://gist.github.com/gre/1650294
* @param {String} type Easing pattern
* @param {Number} time Time animation should take to complete
* @returns {Number}
*/
var easingPattern = function (settings, time) {
var pattern;
// Default Easing Patterns
if (settings.easing === 'easeInQuad') pattern = time * time; // accelerating from zero velocity
if (settings.easing === 'easeOutQuad') pattern = time * (2 - time); // decelerating to zero velocity
if (settings.easing === 'easeInOutQuad') pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration
if (settings.easing === 'easeInCubic') pattern = time * time * time; // accelerating from zero velocity
if (settings.easing === 'easeOutCubic') pattern = (--time) * time * time + 1; // decelerating to zero velocity
if (settings.easing === 'easeInOutCubic') pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration
if (settings.easing === 'easeInQuart') pattern = time * time * time * time; // accelerating from zero velocity
if (settings.easing === 'easeOutQuart') pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity
if (settings.easing === 'easeInOutQuart') pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration
if (settings.easing === 'easeInQuint') pattern = time * time * time * time * time; // accelerating from zero velocity
if (settings.easing === 'easeOutQuint') pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity
if (settings.easing === 'easeInOutQuint') pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration
// Custom Easing Patterns
if (!!settings.customEasing) pattern = settings.customEasing(time);
return pattern || time; // no easing, no acceleration
};
/**
* Determine the document's height
* @returns {Number}
*/
var getDocumentHeight = function () {
return Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
};
/**
* Calculate how far to scroll
* Clip support added by robjtede - https://github.com/cferdinandi/smooth-scroll/issues/405
* @param {Element} anchor The anchor element to scroll to
* @param {Number} headerHeight Height of a fixed header, if any
* @param {Number} offset Number of pixels by which to offset scroll
* @param {Boolean} clip If true, adjust scroll distance to prevent abrupt stops near the bottom of the page
* @returns {Number}
*/
var getEndLocation = function (anchor, headerHeight, offset, clip) {
var location = 0;
if (anchor.offsetParent) {
do {
location += anchor.offsetTop;
anchor = anchor.offsetParent;
} while (anchor);
}
location = Math.max(location - headerHeight - offset, 0);
if (clip) {
location = Math.min(location, getDocumentHeight() - window.innerHeight);
}
return location;
};
/**
* Get the height of the fixed header
* @param {Node} header The header
* @return {Number} The height of the header
*/
var getHeaderHeight = function (header) {
return !header ? 0 : (getHeight(header) + header.offsetTop);
};
/**
* Calculate the speed to use for the animation
* @param {Number} distance The distance to travel
* @param {Object} settings The plugin settings
* @return {Number} How fast to animate
*/
var getSpeed = function (distance, settings) {
var speed = settings.speedAsDuration ? settings.speed : Math.abs(distance / 1000 * settings.speed);
if (settings.durationMax && speed > settings.durationMax) return settings.durationMax;
if (settings.durationMin && speed < settings.durationMin) return settings.durationMin;
return parseInt(speed, 10);
};
var setHistory = function (options) {
// Make sure this should run
if (!history.replaceState || !options.updateURL || history.state) return;
// Get the hash to use
var hash = window.location.hash;
hash = hash ? hash : '';
// Set a default history
history.replaceState(
{
smoothScroll: JSON.stringify(options),
anchor: hash ? hash : window.pageYOffset
},
document.title,
hash ? hash : window.location.href
);
};
/**
* Update the URL
* @param {Node} anchor The anchor that was scrolled to
* @param {Boolean} isNum If true, anchor is a number
* @param {Object} options Settings for Smooth Scroll
*/
var updateURL = function (anchor, isNum, options) {
// Bail if the anchor is a number
if (isNum) return;
// Verify that pushState is supported and the updateURL option is enabled
if (!history.pushState || !options.updateURL) return;
// Update URL
history.pushState(
{
smoothScroll: JSON.stringify(options),
anchor: anchor.id
},
document.title,
anchor === document.documentElement ? '#top' : '#' + anchor.id
);
};
/**
* Bring the anchored element into focus
* @param {Node} anchor The anchor element
* @param {Number} endLocation The end location to scroll to
* @param {Boolean} isNum If true, scroll is to a position rather than an element
*/
var adjustFocus = function (anchor, endLocation, isNum) {
// Is scrolling to top of page, blur
if (anchor === 0) {
document.body.focus();
}
// Don't run if scrolling to a number on the page
if (isNum) return;
// Otherwise, bring anchor element into focus
anchor.focus();
if (document.activeElement !== anchor) {
anchor.setAttribute('tabindex', '-1');
anchor.focus();
anchor.style.outline = 'none';
}
window.scrollTo(0 , endLocation);
};
/**
* Emit a custom event
* @param {String} type The event type
* @param {Object} options The settings object
* @param {Node} anchor The anchor element
* @param {Node} toggle The toggle element
*/
var emitEvent = function (type, options, anchor, toggle) {
if (!options.emitEvents || typeof window.CustomEvent !== 'function') return;
var event = new CustomEvent(type, {
bubbles: true,
detail: {
anchor: anchor,
toggle: toggle
}
});
document.dispatchEvent(event);
};
//
// SmoothScroll Constructor
//
var SmoothScroll = function (selector, options) {
//
// Variables
//
var smoothScroll = {}; // Object for public APIs
var settings, anchor, toggle, fixedHeader, eventTimeout, animationInterval;
//
// Methods
//
/**
* Cancel a scroll-in-progress
*/
smoothScroll.cancelScroll = function (noEvent) {
cancelAnimationFrame(animationInterval);
animationInterval = null;
if (noEvent) return;
emitEvent('scrollCancel', settings);
};
/**
* Start/stop the scrolling animation
* @param {Node|Number} anchor The element or position to scroll to
* @param {Element} toggle The element that toggled the scroll event
* @param {Object} options
*/
smoothScroll.animateScroll = function (anchor, toggle, options) {
// Cancel any in progress scrolls
smoothScroll.cancelScroll();
// Local settings
var _settings = extend(settings || defaults, options || {}); // Merge user options with defaults
// Selectors and variables
var isNum = Object.prototype.toString.call(anchor) === '[object Number]' ? true : false;
var anchorElem = isNum || !anchor.tagName ? null : anchor;
if (!isNum && !anchorElem) return;
var startLocation = window.pageYOffset; // Current location on the page
if (_settings.header && !fixedHeader) {
// Get the fixed header if not already set
fixedHeader = document.querySelector(_settings.header);
}
var headerHeight = getHeaderHeight(fixedHeader);
var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof _settings.offset === 'function' ? _settings.offset(anchor, toggle) : _settings.offset), 10), _settings.clip); // Location to scroll to
var distance = endLocation - startLocation; // distance to travel
var documentHeight = getDocumentHeight();
var timeLapsed = 0;
var speed = getSpeed(distance, _settings);
var start, percentage, position;
/**
* Stop the scroll animation when it reaches its target (or the bottom/top of page)
* @param {Number} position Current position on the page
* @param {Number} endLocation Scroll to location
* @param {Number} animationInterval How much to scroll on this loop
*/
var stopAnimateScroll = function (position, endLocation) {
// Get the current location
var currentLocation = window.pageYOffset;
// Check if the end location has been reached yet (or we've hit the end of the document)
if (position == endLocation || currentLocation == endLocation || ((startLocation < endLocation && window.innerHeight + currentLocation) >= documentHeight)) {
// Clear the animation timer
smoothScroll.cancelScroll(true);
// Bring the anchored element into focus
adjustFocus(anchor, endLocation, isNum);
// Emit a custom event
emitEvent('scrollStop', _settings, anchor, toggle);
// Reset start
start = null;
animationInterval = null;
return true;
}
};
/**
* Loop scrolling animation
*/
var loopAnimateScroll = function (timestamp) {
if (!start) { start = timestamp; }
timeLapsed += timestamp - start;
percentage = speed === 0 ? 0 : (timeLapsed / speed);
percentage = (percentage > 1) ? 1 : percentage;
position = startLocation + (distance * easingPattern(_settings, percentage));
window.scrollTo(0, Math.floor(position));
if (!stopAnimateScroll(position, endLocation)) {
animationInterval = window.requestAnimationFrame(loopAnimateScroll);
start = timestamp;
}
};
/**
* Reset position to fix weird iOS bug
* @link https://github.com/cferdinandi/smooth-scroll/issues/45
*/
if (window.pageYOffset === 0) {
window.scrollTo(0, 0);
}
// Update the URL
updateURL(anchor, isNum, _settings);
// If the user prefers reduced motion, jump to location
if (reduceMotion()) {
window.scrollTo(0, Math.floor(endLocation));
return;
}
// Emit a custom event
emitEvent('scrollStart', _settings, anchor, toggle);
// Start scrolling animation
smoothScroll.cancelScroll(true);
window.requestAnimationFrame(loopAnimateScroll);
};
/**
* If smooth scroll element clicked, animate scroll
*/
var clickHandler = function (event) {
// Don't run if event was canceled but still bubbled up
// By @mgreter - https://github.com/cferdinandi/smooth-scroll/pull/462/
if (event.defaultPrevented) return;
// Don't run if right-click or command/control + click or shift + click
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey) return;
// Check if event.target has closest() method
// By @totegi - https://github.com/cferdinandi/smooth-scroll/pull/401/
if (!('closest' in event.target)) return;
// Check if a smooth scroll link was clicked
toggle = event.target.closest(selector);
if (!toggle || toggle.tagName.toLowerCase() !== 'a' || event.target.closest(settings.ignore)) return;
// Only run if link is an anchor and points to the current page
if (toggle.hostname !== window.location.hostname || toggle.pathname !== window.location.pathname || !/#/.test(toggle.href)) return;
// Get an escaped version of the hash
var hash;
try {
hash = escapeCharacters(decodeURIComponent(toggle.hash));
} catch(e) {
hash = escapeCharacters(toggle.hash);
}
// Get the anchored element
var anchor;
if (hash === '#') {
if (!settings.topOnEmptyHash) return;
anchor = document.documentElement;
} else {
anchor = document.querySelector(hash);
}
anchor = !anchor && hash === '#top' ? document.documentElement : anchor;
// If anchored element exists, scroll to it
if (!anchor) return;
event.preventDefault();
setHistory(settings);
smoothScroll.animateScroll(anchor, toggle);
};
/**
* Animate scroll on popstate events
*/
var popstateHandler = function (event) {
// Stop if history.state doesn't exist (ex. if clicking on a broken anchor link).
// fixes `Cannot read property 'smoothScroll' of null` error getting thrown.
if (history.state === null) return;
// Only run if state is a popstate record for this instantiation
if (!history.state.smoothScroll || history.state.smoothScroll !== JSON.stringify(settings)) return;
// Only run if state includes an anchor
// if (!history.state.anchor && history.state.anchor !== 0) return;
// Get the anchor
var anchor = history.state.anchor;
if (typeof anchor === 'string' && anchor) {
anchor = document.querySelector(escapeCharacters(history.state.anchor));
if (!anchor) return;
}
// Animate scroll to anchor link
smoothScroll.animateScroll(anchor, null, {updateURL: false});
};
/**
* Destroy the current initialization.
*/
smoothScroll.destroy = function () {
// If plugin isn't already initialized, stop
if (!settings) return;
// Remove event listeners
document.removeEventListener('click', clickHandler, false);
window.removeEventListener('popstate', popstateHandler, false);
// Cancel any scrolls-in-progress
smoothScroll.cancelScroll();
// Reset variables
settings = null;
anchor = null;
toggle = null;
fixedHeader = null;
eventTimeout = null;
animationInterval = null;
};
/**
* Initialize Smooth Scroll
* @param {Object} options User settings
*/
var init = function () {
// feature test
if (!supports()) throw 'Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.';
// Destroy any existing initializations
smoothScroll.destroy();
// Selectors and variables
settings = extend(defaults, options || {}); // Merge user options with defaults
fixedHeader = settings.header ? document.querySelector(settings.header) : null; // Get the fixed header
// When a toggle is clicked, run the click handler
document.addEventListener('click', clickHandler, false);
// If updateURL and popState are enabled, listen for pop events
if (settings.updateURL && settings.popstate) {
window.addEventListener('popstate', popstateHandler, false);
}
};
//
// Initialize plugin
//
init();
//
// Public APIs
//
return smoothScroll;
};
return SmoothScroll;
}));

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
---
layout: single
title: Contact
permalink: /contact/
---
You can contact me via:
- Telegram: <a href="https://t.me/sahinakkaya">@sahinakkaya</a>
- Matrix: <a href="https://matrix.to/#/@sahinakkaya:matrix.org">sahinakkaya:matrix.org</a>
- E-mail: <a href="mailto:sahin@sahinakkaya.dev">sahin@sahinakkaya.dev</a>
And [here](/assets/docs/public.pgp) is my public GPG key if you need.

389
contact/index.html 100644
View File

@ -0,0 +1,389 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Contact - Şahin Akkayas Personal Page</title>
<meta name="description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<meta name="author" content="Şahin Akkaya">
<meta property="og:type" content="website">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Contact">
<meta property="og:url" content="https://sahinakkaya.dev/contact/">
<meta property="og:description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<link rel="canonical" href="https://sahinakkaya.dev/contact/">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="https://schema.org/CreativeWork">
<meta itemprop="headline" content="Contact">
<div class="page__inner-wrap">
<header>
<h1 id="page-title" class="page__title" itemprop="headline">Contact
</h1>
</header>
<section class="page__content" itemprop="text">
<p>You can contact me via:</p>
<ul>
<li>Telegram: <a href="https://t.me/sahinakkaya">@sahinakkaya</a>
</li>
<li>Matrix: <a href="https://matrix.to/#/@sahinakkaya:matrix.org">sahinakkaya:matrix.org</a>
</li>
<li>E-mail: <a href="mailto:sahin@sahinakkaya.dev">sahin@sahinakkaya.dev</a>
</li>
</ul>
<p>And <a href="/assets/docs/public.pgp">here</a> is my public GPG key if you need.</p>
</section>
<footer class="page__meta">
</footer>
</div>
</article>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

690
feed.xml 100644
View File

@ -0,0 +1,690 @@
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.1">Jekyll</generator><link href="https://sahinakkaya.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sahinakkaya.dev/" rel="alternate" type="text/html" /><updated>2023-02-14T09:02:59+00:00</updated><id>https://sahinakkaya.dev/feed.xml</id><title type="html">Şahin Akkayas Personal Page</title><subtitle>Şahin Akkaya's personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.</subtitle><author><name>Şahin Akkaya</name></author><entry><title type="html">Hot-Reload Long Running Shell Scripts (feat. trap / kill)</title><link href="https://sahinakkaya.dev/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="alternate" type="text/html" title="Hot-Reload Long Running Shell Scripts (feat. trap / kill)" /><published>2023-01-15T21:48:08+00:00</published><updated>2023-01-15T21:48:08+00:00</updated><id>https://sahinakkaya.dev/2023/01/15/hot-reloading-with-trap-and-kill</id><content type="html" xml:base="https://sahinakkaya.dev/2023/01/15/hot-reloading-with-trap-and-kill.html">&lt;h2 id=&quot;trap-them-and-kill-them&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trap&lt;/code&gt; them and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt; them!&lt;/h2&gt;
&lt;p&gt;There is a beautiful command in Linux called &lt;a href=&quot;https://man7.org/linux/man-pages/man1/trap.1p.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trap&lt;/code&gt;&lt;/a&gt; which &lt;em&gt;trap&lt;/em&gt;s signals and let you run specific commands when they invoked. There is also good ol &lt;a href=&quot;https://man7.org/linux/man-pages/man1/kill.1.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt;&lt;/a&gt; command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!&lt;/p&gt;
&lt;h3 id=&quot;basic-example&quot;&gt;Basic Example&lt;/h3&gt;
&lt;p&gt;Lets start by creating something very simple and build up from there. Create a script with the following contents:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;My pid is &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;. Send me SIGUSR1!&quot;&lt;/span&gt;
func&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Got SIGUSR1&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# here we are telling that run 'func' when USR1 signal is&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# received. You can run anything. Combine commands with ; etc.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;trap&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;func&quot;&lt;/span&gt; USR1
&lt;span class=&quot;c&quot;&gt;# The while loop is important here otherwise our script will exit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# before we manage to get a chance to send a signal.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;waiting SIGUSR1&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now make it executable and run it:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x trap_example
./trap_example
My pid is 2811137. Send me SIGUSR1!
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
waiting SIGUSR1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Open another terminal and send your signal with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt; to the specified pid.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;kill&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; USR1 2811137
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You should receive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;Got SIGUSR!&quot;&lt;/code&gt; from the other process. Thats it! Now, imagine you write whatever thing you want to execute in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func&lt;/code&gt; and then you can simply &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill -s ...&lt;/code&gt; anytime and as many times you want!&lt;/p&gt;
&lt;p&gt;Lets move the while loop into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func&lt;/code&gt; and add some variables so you can see how powerful this is.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;My pid is &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;. Send me SIGUSR1!&quot;&lt;/span&gt;
func&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;i: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt; i &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;trap&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;echo 'Got SIGUSR1!'; func&quot;&lt;/span&gt; USR1
&lt;span class=&quot;c&quot;&gt;# we need to call the function once, otherwise script&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# will exit before we manage to send a signal&lt;/span&gt;
func
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now run the script and send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SIGUSR1&lt;/code&gt;. Here is the result:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ./trap_example
My pid is 2880704. Send me SIGUSR1!
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
Got SIGUSR1!
i: 1
i: 2
i: 3
i: 4
i: 5
Got SIGUSR1!
i: 1
i: 2
^C
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Isnt this neat?&lt;/p&gt;
&lt;h3 id=&quot;more-useful-example&quot;&gt;More useful example&lt;/h3&gt;
&lt;p&gt;Lets imagine you have multiple long running (infinite loops basically) scripts and you want to restart them without manually searching for their pids and killing them. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trap&lt;/code&gt; is for the rescue, again! &lt;sup&gt;&lt;a href=&quot;##&quot; title=&quot;Yeah, I know you can run a systemd service if you want but I think it is an overkill for this situation. Plus, I don't like dealing with them.&quot;&gt;*&lt;/a&gt;&lt;/sup&gt; This command is awesome.&lt;/p&gt;
&lt;p&gt;Without further ado, lets get started. Create a script called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script1&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# file: script1&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello from &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;. i is &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt; i &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And symlink it to another name just for fun:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x script1
&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; script1 script2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now we can pretend they are two different scripts as their outputs differ:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ./script1
Hello from ./script1. i is 1
Hello from ./script1. i is 2
Hello from ./script1. i is 3
Hello from ./script1. i is 4
^C
./script2
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script2. i is 3
^C
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Finally, create the main script which will start child scripts and restart them on our signals:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;My pid is &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;. You know what to do ( ͡° ͜ʖ ͡°)&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You can also kill me with 'kill -s INT -&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pgrep -f &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;'&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pids&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# we will store the pid's of child scripts here&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scripts_to_be_executed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./script1&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./script2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
kill_childs&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# wow, this sounded wild&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;pid &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;killing &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pid&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -P: kill all the processes whose parent process is 'pid'&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# see how we are creating processes below&lt;/span&gt;
pkill &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pid&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pids&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kill childs and restart all the scripts&lt;/span&gt;
restart_scripts&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
kill_childs
&lt;span class=&quot;c&quot;&gt;# for each script in the list&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;script &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;scripts_to_be_executed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Run the script and store its pid.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# note the '&amp;amp;' at the end of command. Without it the script will&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# block until its execution is finished. Also we are putting it&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# into braces because we want to create a &quot;process group&quot; so that&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# we can kill all its children later by specifying parent pid&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# (useful if you have pipes (|) or other &amp;amp;'s in your script!)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$script&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;amp;
pids+&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$!&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# we will restart_scripts with SIGUSR1 signal&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;trap&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'echo &quot;restarting scripts&quot;; restart_scripts'&lt;/span&gt; USR1
&lt;span class=&quot;c&quot;&gt;# we will kill all the childs and exit the main script with SIGINT&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# which is same signal as when you press &amp;lt;Control-C&amp;gt; on your terminal&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;trap&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'echo exiting; kill_childs; exit'&lt;/span&gt; INT
&lt;span class=&quot;c&quot;&gt;# run the function once&lt;/span&gt;
restart_scripts
&lt;span class=&quot;c&quot;&gt;# infinite loop, otherwise main script will exit before we send signal.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# remember, we started child processes with '&amp;amp;' so they won't block this script&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now, you can run your main script and reload your child scripts any time with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;killall main_script -USR1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Here is an example run:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ./trap_multiple
My pid is 3124123. You know what to do ( ͡° ͜ʖ ͡°)
You can also kill me with 'kill -s INT -`pgrep -f trap_multiple`'
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script1. i is 2
Hello from ./script2. i is 3
Hello from ./script1. i is 3
restarting scripts
killing 3124125
killing 3124126
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script2. i is 2
Hello from ./script1. i is 2
Hello from ./script2. i is 3
Hello from ./script1. i is 3
Hello from ./script2. i is 4
Hello from ./script1. i is 4
restarting scripts
killing 3124304
killing 3124305
Hello from ./script1. i is 1
Hello from ./script2. i is 1
Hello from ./script1. i is 2
Hello from ./script2. i is 2
^Cexiting
killing 3124875
killing 3124876
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;final-words&quot;&gt;Final words&lt;/h3&gt;
&lt;p&gt;I think I am started to getting obsessed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trap&lt;/code&gt; command because it has such a good name and purpose. FOSS people are really on another level when it comes to naming. Here is another good one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;- How can you see the contents of a file? &lt;br /&gt;
+ You &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt;&lt;/em&gt; it. &lt;br /&gt;
- What if you want to see them in reverse order? &lt;br /&gt;
+ You &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tac&lt;/code&gt;&lt;/em&gt; it. &lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No, it is not just a joke. Try it… Man I love Gnoo slash Linux.&lt;/p&gt;
&lt;p&gt;Anyway, I hope now you know how to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trap&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill&lt;/code&gt;. Next week I will explain how to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unzip; strip; touch; finger; grep; mount; fsck; more; yes; fsck; fsck; umount; clean; sleep&lt;/code&gt; &lt;nobr&gt;( ͡° ͜ʖ ͡°)&lt;/nobr&gt;. &lt;sup&gt;&lt;a href=&quot;##&quot; title=&quot;jk :D&quot;&gt;*&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="trap" /><category term="kill" /><category term="linux" /><summary type="html">trap them and kill them! There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is also good ol kill command which not only kills processes but allows you to specify a signal to send. By combining these two, you can run specific functions from your scripts any time!</summary></entry><entry><title type="html">Recap of 2022</title><link href="https://sahinakkaya.dev/2022/12/29/recap-of-2022.html" rel="alternate" type="text/html" title="Recap of 2022" /><published>2022-12-29T20:22:08+00:00</published><updated>2022-12-29T20:22:08+00:00</updated><id>https://sahinakkaya.dev/2022/12/29/recap-of-2022</id><content type="html" xml:base="https://sahinakkaya.dev/2022/12/29/recap-of-2022.html">&lt;p&gt;Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.&lt;/p&gt;
&lt;p&gt;The biggest problem of my life is the graduation project. Oh, God it is making me sick! I simply dont have any interest for the subject I am supposed to work on. One part of me saying that “come on, you came this far. You are nearly finished. One last push!” and other part of me saying “oh no, dont do it. You have never done something you dont like in your entire life. F*ck it!”. So I am wasting my time each term with the dilemma I just described. I really dont know what to do. This thing is fed up.&lt;/p&gt;
&lt;p&gt;Second biggest problem is I live in Turkey. I feel like all my friends somehow get rid of this sh*thole and I am locked here. I use Twitter and Reddit to consume daily news and almost everyday I encounter something that make me say “F*ck me, why I am still here? There is no hope”. Actually, the situation was much worse while I was following pages that shares “street interviews”. At first I started watching them &lt;em&gt;for fun&lt;/em&gt; but the stupidity of people was real and harming my mental health. Since that day, I started consuming only news. My experience got better but I feel like it is still affecting me in a bad manner because everyday something bad happens and there is not much I can do to fix. Today, I decided to delete Twitter and Reddit. Ill see how it goes.&lt;/p&gt;
&lt;p&gt;I am living with my parents for the past 6 months, I break up with my girlfriend, I left the place I was working. Man, this could be the worst year of my life!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/recap-2022/jackie-chan-wtf.jpg&quot; alt=&quot;Jackie Chan WTF meme&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You know what? I am not gonna give up. &lt;em&gt;“… It aint about how hard you get hit. Its about how hard you get hit and keep moving forward. How much you can take, and keep moving forward…”&lt;/em&gt; No, seriously things really will be different for me in 2023 I can feel it. I learn from my mistakes, they are making me even more perfect :D I love myself, I got this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/recap-2022/i-got-this.jpg&quot; alt=&quot;Disaster girl saying &amp;quot;I got this&amp;quot;&quot; /&gt;&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><summary type="html">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.</summary></entry><entry><title type="html">Rant: Stop whatever you are doing and learn how licenses work</title><link href="https://sahinakkaya.dev/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="alternate" type="text/html" title="Rant: Stop whatever you are doing and learn how licenses work" /><published>2022-06-22T07:46:00+00:00</published><updated>2022-06-22T07:46:00+00:00</updated><id>https://sahinakkaya.dev/2022/06/22/rant-on-peoples-reaction-to-copilot</id><content type="html" xml:base="https://sahinakkaya.dev/2022/06/22/rant-on-peoples-reaction-to-copilot.html">&lt;p&gt;Recently, Github &lt;a href=&quot;https://github.blog/changelog/2022-06-21-github-copilot-is-now-available-to-individual-developers/&quot;&gt;announced&lt;/a&gt;
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list.
When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pay the subscription fee and get it.&lt;/li&gt;
&lt;li&gt;Prove you are a student and get it for free.&lt;/li&gt;
&lt;li&gt;Be a maintainer of &lt;em&gt;a popular repository&lt;/em&gt; and get it for free.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think I should be able to use it for free because I am a student but apparently they are not convinced yet. Anyways, that is a different
story. I dont care if they will give me access to Github Copilot or not. It is not a big deal for me.&lt;/p&gt;
&lt;p&gt;But some people were really angry about how Github Team being vague while defining the criteria as “being a maintainer of a popular open source project”.
I think they are right to some extent. If all you need is having a few thousands stars for a project, you could easily get that. I know a lot of troll
or low effort repositories that get a lot of stars because they are funny.&lt;/p&gt;
&lt;p&gt;Later, I found &lt;a href=&quot;https://twitter.com/fatih/status/1539574219629105156&quot;&gt;another tweet&lt;/a&gt; that explains how Github decides what is &lt;em&gt;popular&lt;/em&gt;. According to
this tweet, if you have a repository that is in top 1000 in one of the most popular 34 languages, you are eligible to get Github Copilot for free.
This is better than the previous definition but you can still argue that it is not fair because one can create a package for checking if a number is
even or not and get thousands of stars.&lt;/p&gt;
&lt;p&gt;You can criticize this, I get that. But do not come up with silly arguments to justify yourself. Like how on earth would you think that Github is doing
something bad because $10/month is too much for this service? It is business man, you pay if you think it is worth it. Thats it. &lt;em&gt;“I joined beta program
and it was free, now they want to charge me if I want to continue using it. They did not tell me that.”&lt;/em&gt; Uhhm… What? Are you aware that what you are using
is another companys service and they have all rights to do whatever they want with their service? How you guys even can build up arguments like that?! This is crazy!&lt;/p&gt;
&lt;p&gt;Some people argue that &lt;em&gt;“what Github is doing is wrong because they used open source projects &lt;strong&gt;without consent&lt;/strong&gt;.”&lt;/em&gt; Another similar argument is that &lt;em&gt;“what
Github is doing is evil because they used projects developed by community and now they are selling it without giving any money to the contributors of
these projects.”&lt;/em&gt; Do you guys even have an idea what licenses stands for? If you dont want to some random person use your code, just license it that
way. And if you licensed it with a GPL compatible or similar license you already gave rights anyone to use or sell your code. That is not Githubs
problem. That is your problem not understanding how licenses work. Stop complaining.&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="copilot" /><category term="license" /><category term="github" /><summary type="html">Recently, Github announced that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting list. When I saw the news, I thought I can give it a try. But not so surprisingly it was not free. You have 3 ways to get it: Pay the subscription fee and get it. Prove you are a student and get it for free. Be a maintainer of a popular repository and get it for free.</summary></entry><entry><title type="html">Confession Time</title><link href="https://sahinakkaya.dev/2022/04/08/confession-time.html" rel="alternate" type="text/html" title="Confession Time" /><published>2022-04-08T15:46:00+00:00</published><updated>2022-04-13T00:00:00+00:00</updated><id>https://sahinakkaya.dev/2022/04/08/confession-time</id><content type="html" xml:base="https://sahinakkaya.dev/2022/04/08/confession-time.html">&lt;h2 id=&quot;a-failure-story&quot;&gt;A failure story&lt;/h2&gt;
&lt;p&gt;Last week, I received an email from &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Lets Encrypt&lt;/a&gt; reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I cant send or receive any emails. If you send me email in the last week and wonder why I didnt respond, this is the reason.&lt;/p&gt;
&lt;p&gt;Anyway, I thought it will be easy to fix. Just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot&lt;/code&gt; again and let him do the job, right? NOPE. It is not that easy. It is just giving me errors with some success messages. If I was not so clueless about what the heck I am doing, I could fix the error. But I dont know anything about how SSL works and it is a shame.&lt;/p&gt;
&lt;p&gt;I dont even know the subject enough to Google it. I feel like I am the only guy in the planet whose certificate is expired. Seriously, how tf I cant find a solution to a such common problem? There was a saying like, &lt;em&gt;“If you cant find something on the internet, there is a high chance that you are being stupid”&lt;/em&gt;. It was not exactly like this but I cant find the original quote either. Argghh…&lt;/p&gt;
&lt;p&gt;If you know the original quote, email me… No, do not email because it does not work. F%ck this thing. F*%k everything. I deserved this. Do not help. If I cant fix this by myself, I should not call myself computer engineer. I am out.&lt;/p&gt;
&lt;h3 id=&quot;update&quot;&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The problem is fixed. One of my colleagues told me to reboot the server so that it will (&lt;em&gt;possibly&lt;/em&gt;) trigger a script to get a new certificate. I did not think it would work because I already try to get a new certificate manually running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot renew&lt;/code&gt;. And yeah, it didnt change anything but gave me courage to try other &lt;em&gt;dead simple&lt;/em&gt; solutions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;One of them was adding missing MX records for my domain. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot&lt;/code&gt; was telling me that it cant find any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AAAA&lt;/code&gt; records for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.mail&lt;/code&gt;. I didnt think this is related with my problem because how would I receive emails before then? Anyway, I added the records and the errors are gone. It was only giving me success messages now. Everything seemed to be fine. But I still could not connect to my mail account.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And here is the solution: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl restart dovecot&lt;/code&gt;. Kill me. I am &lt;em&gt;guessing&lt;/em&gt; I had to restart the mail service because certificate has changed and it had to pick up the new one. I bet if I had run this command right after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot renew&lt;/code&gt; I would not face any issues. The error messages caused by missing mx records were not related with this problem but I was confused by them and I thought something wrong with my certificates.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any way, I am happy that it is finally fixed. Did I learn something from this? Not much. But yeah, sometimes all you need is a simple restart :D&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="ssl" /><summary type="html">A failure story Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. Now I cant send or receive any emails. If you send me email in the last week and wonder why I didnt respond, this is the reason.</summary></entry><entry><title type="html">Never Get Trapped in Grub Rescue Again!</title><link href="https://sahinakkaya.dev/2022/03/03/never-get-trapped-in-grub-rescue-again.html" rel="alternate" type="text/html" title="Never Get Trapped in Grub Rescue Again!" /><published>2022-03-03T00:46:00+00:00</published><updated>2022-03-03T00:46:00+00:00</updated><id>https://sahinakkaya.dev/2022/03/03/never-get-trapped-in-grub-rescue-again</id><content type="html" xml:base="https://sahinakkaya.dev/2022/03/03/never-get-trapped-in-grub-rescue-again.html">&lt;p&gt;Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” menu and I dont know how to fix things from that point.&lt;/p&gt;
&lt;p&gt;I go into the live environment and run some random commands that I found on the internet and hope for the best.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/grub-rescue/random-bullshit.jpg&quot; alt=&quot;me trying to fix grub&quot; /&gt;&lt;/p&gt;
&lt;p&gt;What a nice way to shoot myself in the foot! But this time is different. This time, I f*cked up so much that even the random commands on the internet could not help me. I was on my own and I needed to figure out what is wrong with my system. Let me tell you what I did:&lt;/p&gt;
&lt;p&gt;I decided to install another OS just to try it in a real machine. I wanted to shrink one of my partitions to create a space for the new system. I run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdisk /dev/sdb&lt;/code&gt;, the very first message that it tells me was&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;This disk is currently in use - repartitioning is probably a bad idea. It's recommended to umount all file systems, and swapoff all swap partitions on this disk.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yes, it just screams &lt;strong&gt;&lt;em&gt;“Do not do it!”&lt;/em&gt;&lt;/strong&gt; but come on. I will not try to shrink the partition I am using (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb3&lt;/code&gt;). So it should not be a problem. I ignored the message and shrink it anyway. No problem. Installed and tested the new OS a little bit. Time to reboot and hope for the best. And of course it did not boot. What would I even expecting?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/grub-rescue/cj.png&quot; alt=&quot;ah sh*t here we go again&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As always, I booted into a live environment and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boot-repair&lt;/code&gt; command. It was always working but this time… Even after finishing the operation successfully I could not boot into neither Arch nor Ubuntu (the two systems I had previously).&lt;/p&gt;
&lt;p&gt;Arch was originally mounted in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb3&lt;/code&gt; and Ubuntu was in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sda2&lt;/code&gt;. Considering the fact that I only messed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb&lt;/code&gt;, I should be able to boot Ubuntu, right? Well, yeah. Technically I did boot into Ubuntu but I didnt see the login screen. It was dropping me into something called &lt;em&gt;“Emergency mode”&lt;/em&gt; which just makes me panic! &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo update-grub&lt;/code&gt;… Nope. Nothing changes. Arch does not boot and Ubuntu partially boots.&lt;/p&gt;
&lt;p&gt;Let me tell you what the problem was and how my ignorance made it worse:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;While installing the new system, I saw a partition &lt;strong&gt;labelled&lt;/strong&gt; &lt;em&gt;“Microsoft Basic Data”&lt;/em&gt;. I deleted it thinking it is not required because I dont use W*ndows. It turns out, it was my &lt;em&gt;boot&lt;/em&gt; partition for Arch, just labelled incorrectly… Big lolz :D But we will see this is not even important because I had to rewrite my boot partition anyway.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;My Arch was installed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb3&lt;/code&gt;. When I created a new partition and installed the new system, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb3&lt;/code&gt; was shifted to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb5&lt;/code&gt; even though I did not ask for it. But the grub configuration to boot my system was still pointing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb3&lt;/code&gt;. That was the reason why Arch does not boot. It was trying to boot from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb3&lt;/code&gt;. So I had to recreate grub configuration and reinstall grub to fix it. I run the following commands that I found &lt;a href=&quot;https://www.jeremymorgan.com/tutorials/linux/how-to-reinstall-boot-loader-arch-linux/&quot;&gt;here&lt;/a&gt; in a live Arch environment:
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /mnt/arch
mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; auto /dev/sdb5 /mnt/arch
arch-chroot /mnt/arch
mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; auto /dev/sdb4 /boot/efi
os-prober
grub-mkconfig &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /boot/grub/grub.cfg
grub-install &lt;span class=&quot;nt&quot;&gt;--efi-directory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/boot/efi &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;x86_64-efi /dev/sdb
&lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/div&gt;
&lt;p&gt;And it fixed my grub. I can now boot into Arch, hooray!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ubuntu was not still booting properly. I checked the logs with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;journalctl -xb&lt;/code&gt; and saw something related with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb&lt;/code&gt;. Ubuntu was installed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sda2&lt;/code&gt;, why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb&lt;/code&gt; should be a problem? Then I remembered something. Back in times when I was using Ubuntu, I was using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb1&lt;/code&gt; as a secondary storage. So I had a configuration where it automatically mounts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb1&lt;/code&gt; on startup. Since I messed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdb1&lt;/code&gt; , it was failing to mount it. I opened &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt;, and deleted the related line. Bingo! It started booting properly.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/grub-rescue/hackerman.jpg&quot; alt=&quot;i am something of a hackerman myself&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I started feeling like Hackerman, and I said to myself &lt;em&gt;“You know what, Imma fix everything.”&lt;/em&gt; I had a very sh*tty grub menu with useless grub entries from old systems that I dont use anymore. The UEFI also had the same problem. It had ridiculous amount of boot entries that most of them are just trash.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/grub-rescue/shitty-uefi.jpg&quot; alt=&quot;the pictures i took while trying to figure out which boot options are useless&quot; /&gt;&lt;/p&gt;
&lt;p&gt;These are the pictures I took for reference while trying to figure out which boot options are useless. Sorry for the bad quality. I didnt think I would use them in a blog post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;While trying to fix the previous problems, Ive spent enough time in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/efi&lt;/code&gt; directory that make me understand where these grub entries are coming from. There were a lot of files belong to old systems. I simply deleted them and updated grub. All of the bad entries were gone. I want to draw your attention here: &lt;em&gt;I did not search for how to delete the unused grub entries. I just knew deleting their directories from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/efi&lt;/code&gt; will do the job. I am doing this sh*t! (Another hackerman moment :D )&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;In order to delete useless boot options from UEFI menu, I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;efibootmgr&lt;/code&gt;. I searched for it on the internet, of course!
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;efibootmgr &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Check which entries you want to delete, say it is 0003.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;efibootmgr &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 0003 &lt;span class=&quot;nt&quot;&gt;-B&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# This will delete third boot option. &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And finally! I know everything about how all these work. Another shady part of Linux is clear for me. Now:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/grub-rescue/quote.jpg&quot; alt=&quot;Give me a ruined computer and an Arch ISO, and I shall fix it for you.&quot; /&gt;&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="linux" /><category term="grub" /><category term="partition" /><category term="uefi" /><summary type="html">Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” menu and I dont know how to fix things from that point.</summary></entry><entry><title type="html">Creating a *Useless* User</title><link href="https://sahinakkaya.dev/2022/02/27/creating-a-useless-user.html" rel="alternate" type="text/html" title="Creating a *Useless* User" /><published>2022-02-27T13:40:00+00:00</published><updated>2022-02-27T13:40:00+00:00</updated><id>https://sahinakkaya.dev/2022/02/27/creating-a-useless-user</id><content type="html" xml:base="https://sahinakkaya.dev/2022/02/27/creating-a-useless-user.html">&lt;h2 id=&quot;story&quot;&gt;Story&lt;/h2&gt;
&lt;p&gt;In my &lt;a href=&quot;/2022/02/26/ssh-into-machine-that-is-behind-private-network.html&quot;&gt;previous post&lt;/a&gt;, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriends computer. Now, of course I dont want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;
&lt;p&gt;I searched the problem in it turned out to be very simple. You just need to add two additional flags to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adduser&lt;/code&gt; command while creating the user.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;adduser uselessuser &lt;span class=&quot;nt&quot;&gt;--shell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/bin/false &lt;span class=&quot;nt&quot;&gt;--no-create-home&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uselessuser&lt;/code&gt; cant do anything useful in your server. If they try to login, the connection will be closed immediately.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ssh uselessuser@remote.host
uselessuser@remote.host&lt;span class=&quot;se&quot;&gt;\'&lt;/span&gt;s password:
Could not chdir to home directory /home/uselessuser: No such file or directory
Connection to remote.host closed.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;But they can still do forward the remote port to their local machine.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ssh &lt;span class=&quot;nt&quot;&gt;-Nf&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; 7777:localhost:22 uselessuser@remote.host
uselessuser@remote.host&lt;span class=&quot;se&quot;&gt;\'&lt;/span&gt;s password:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; option is the most important one here. From the documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; -N Do not execute a remote command. This is useful
for just forwarding ports. Refer to the description
of SessionType in ssh_config(5) for details.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/div&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;last-words&quot;&gt;Last words&lt;/h2&gt;
&lt;p&gt;I love learning new things everyday. I knew setting the shell of a user to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin/false&lt;/code&gt; will prevent them from logging in. The reason I wrote this blog post is because 2 things I wanted to share:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;While looking for a solution to the problem I mentioned, I searched &lt;em&gt;“create a user with no privileges in linux”&lt;/em&gt; and &lt;a href=&quot;https://askubuntu.com/questions/1174376/how-to-create-a-user-with-the-least-privileges-permissions-but-enough-to-do-ssh&quot;&gt;this&lt;/a&gt; came out. It is really interesting for me that another person wanted to do the same thing for the &lt;em&gt;exact same reasons&lt;/em&gt;. They were also trying port forwarding via ssh and they wanted to create a limited user in their server to give friends. So the question was a &lt;strong&gt;perfect fit&lt;/strong&gt; to the problem.&lt;/li&gt;
&lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; flag of the ssh command was also surprising for me. It was like as if someone had encountered these problems before and just took the exact steps required to solve this problem for me. I mean look at the documentation. Crazy!&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Şahin Akkaya</name></author><category term="linux" /><category term="permissions" /><category term="privileges" /><summary type="html">Story In my previous post, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in our desktop at home or my girlfriends computer. Now, of course I dont want to give them access to my server. But they also need to have a user in my server to be able to perform port forwarding via ssh. So I wanted to create a user with least privileges to make sure nothing goes wrong.</summary></entry><entry><title type="html">SSH into Machine That Is Behind a Private Network</title><link href="https://sahinakkaya.dev/2022/02/26/ssh-into-machine-that-is-behind-private-network.html" rel="alternate" type="text/html" title="SSH into Machine That Is Behind a Private Network" /><published>2022-02-26T21:40:00+00:00</published><updated>2022-02-26T21:40:00+00:00</updated><id>https://sahinakkaya.dev/2022/02/26/ssh-into-machine-that-is-behind-private-network</id><content type="html" xml:base="https://sahinakkaya.dev/2022/02/26/ssh-into-machine-that-is-behind-private-network.html">&lt;h2 id=&quot;story&quot;&gt;Story&lt;/h2&gt;
&lt;p&gt;I believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.&lt;/p&gt;
&lt;h2 id=&quot;possible-solutions&quot;&gt;Possible solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Just tell the non-tech people at home to configure the router to forward ssh traffic to desktop, right? Well, this is not an option for me, not because people are non-tech, but there is no router! The desktop is connected to internet via hotspot from mobile phone. There is no root access in the phone and even if there was, it is a really big pain to forward the packets manually. Trust me. Been there, done that!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are tools like &lt;a href=&quot;https://www.ngrok.com&quot;&gt;ngrok&lt;/a&gt;, &lt;a href=&quot;localtunnel.me&quot;&gt;localtunnel&lt;/a&gt; which exposes your localhost to the internet and gives you a URL to access it but I did not want to use them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I did not want to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngrok&lt;/code&gt; because it is not open source and it might have security issues. They are also charging you.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localtunnel&lt;/code&gt; seemed perfect. The code of both client and server is open. That is great news! But it did not last long because it is just forwarding http/https traffic :(&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;I was thinking of extending the functionality of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localtunnel&lt;/code&gt;, but I learned a very simple way. You dont need any external program to overcome this issue. The good old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; can do that! All you need is another machine (a remote server) that both computers can access via ssh.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# local machine (my home computer)&lt;/span&gt;
ssh &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; 7777:localhost:22 remote-user@remote.host
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This command forwards all the incoming connections to port 7777 of remote machine to port 22 of our current machine. In order for this to work, you need to make sure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GatewayPorts&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yes&lt;/code&gt; in the remote server ssh configuration. It also assumes our current machine accepts ssh connections via port 22.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Now, go to any machine and connect to the remote server first. When we are connected, we will create another ssh connection to port 7777 to connect our home computer.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# another local machine (my laptop)&lt;/span&gt;
ssh remote-user@remote.host
&lt;span class=&quot;c&quot;&gt;# connected remote&lt;/span&gt;
ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 7777 homeuser@localhost
&lt;span class=&quot;c&quot;&gt;# we are now connected to home computer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The last two command can also combined so that we directly hop into the home computer.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; remote-user@remote.host ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 7777 homeuser@localhost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;result&quot;&gt;Result&lt;/h3&gt;
&lt;p&gt;As a result, it only took us 2 simple ssh commands to do this. This is just unbelievable! Now, I need to find a way to make non-tech people at home run this command when there is a problem. Too bad Linux cant help me there :D&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="ssh" /><category term="private-network" /><category term="remote-port-forwarding" /><summary type="html">Story I believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should ask this person. I am the tech support in our house. Today, I had to fix a problem in our desktop. Since I was not at home, I had to fix the problem remotely.</summary></entry><entry><title type="html">Using ffmpeg for Simple Video Editing</title><link href="https://sahinakkaya.dev/2022/01/21/ffmpeg-to-rescue.html" rel="alternate" type="text/html" title="Using ffmpeg for Simple Video Editing" /><published>2022-01-21T20:40:00+00:00</published><updated>2022-01-21T20:40:00+00:00</updated><id>https://sahinakkaya.dev/2022/01/21/ffmpeg-to-rescue</id><content type="html" xml:base="https://sahinakkaya.dev/2022/01/21/ffmpeg-to-rescue.html">&lt;h2 id=&quot;story&quot;&gt;Story&lt;/h2&gt;
&lt;p&gt;Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up &lt;a href=&quot;https://kdenlive.org/en/&quot;&gt;Kdenlive&lt;/a&gt; and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ffmpeg&lt;/code&gt; a shot.&lt;/p&gt;
&lt;h2 id=&quot;let-the-show-begin&quot;&gt;Let the show begin&lt;/h2&gt;
&lt;p&gt;Like Kdenlive, I have never used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ffmpeg&lt;/code&gt; before. Like every normal Linux user do, I opened up a terminal and typed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man ffmpeg&lt;/code&gt; to learn how to use it… Just kidding :D I opened a browser and typed &lt;em&gt;“ffmpeg cut video by time”&lt;/em&gt;. Not the best search query, but it was good enough to find what I am looking for as the &lt;a href=&quot;https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg&quot;&gt;first result&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;cutting-the-videos-based-on-start-and-end-time&quot;&gt;Cutting the videos based on start and end time&lt;/h3&gt;
&lt;p&gt;According to answers on the page I mentioned, I run the following commands to cut my video into two parts:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ffmpeg &lt;span class=&quot;nt&quot;&gt;-ss&lt;/span&gt; 00:00:00 &lt;span class=&quot;nt&quot;&gt;-to&lt;/span&gt; 00:01:55 &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; input.mov &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; copy part1.mp4 &lt;span class=&quot;c&quot;&gt;# take from 00:00 to 01:55&lt;/span&gt;
ffmpeg &lt;span class=&quot;nt&quot;&gt;-ss&lt;/span&gt; 00:02:03 &lt;span class=&quot;nt&quot;&gt;-to&lt;/span&gt; 00:05:17 &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; input.mov &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; copy part2.mp4 &lt;span class=&quot;c&quot;&gt;# take from 02:03 to 05:17&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;These two commands run &lt;strong&gt;instantly&lt;/strong&gt;! Kdenlive was still rendering… The progress was 46%. Meh… I said “Duck it, I am gonna use ffmpeg only” and cancelled the rendering.&lt;/p&gt;
&lt;h3 id=&quot;concatenating-the-video-files&quot;&gt;Concatenating the video files&lt;/h3&gt;
&lt;p&gt;Now we have two videos that we want to join. Guess what will be our next search query? &lt;em&gt;“ffmpeg join videos”&lt;/em&gt;. And &lt;a href=&quot;https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg&quot;&gt;here&lt;/a&gt; is the first result:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;file part1.mp4 &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; mylist.txt
&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;file part2.mp4 &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; mylist.txt
ffmpeg &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; concat &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; mylist.txt &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; copy result.mp4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And we are DONE! How easy was that? Whole process took about 10 minutes including my search on the internet. If I continued waiting for Kdenlive to finish rendering, I would probably be still waiting at that time. I love the power of command line!&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="cli" /><category term="ffmpeg" /><summary type="html">Story Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds where I misspelled some words and started again. I had to remove that part from the video before uploading it. Since I was low on time, I thought that I better use a GUI program to do this job. I opened up Kdenlive and jumped into editing my video. It was my first time using it so I spent some time to cut and delete the parts that I want to get rid of. When I was ready, I clicked Render button to render my video. It was waaay too slow than I expected. Since I have nothing to do while waiting for render to finish, I thought I could give ffmpeg a shot.</summary></entry><entry><title type="html">Automatically Build and Deploy Your Site using GitHub Actions and Webhooks</title><link href="https://sahinakkaya.dev/2022/01/04/build-and-deploy-automatically.html" rel="alternate" type="text/html" title="Automatically Build and Deploy Your Site using GitHub Actions and Webhooks" /><published>2022-01-04T17:40:00+00:00</published><updated>2022-01-04T17:40:00+00:00</updated><id>https://sahinakkaya.dev/2022/01/04/build-and-deploy-automatically</id><content type="html" xml:base="https://sahinakkaya.dev/2022/01/04/build-and-deploy-automatically.html">&lt;p&gt;In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.&lt;/p&gt;
&lt;h2 id=&quot;introduction-to-github-actions-and-webhooks&quot;&gt;Introduction to GitHub Actions and Webhooks&lt;/h2&gt;
&lt;p&gt;Let me start by explaining what are GitHub Actions and GitHub Webhooks.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Github Actions&lt;/strong&gt; is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Webhooks&lt;/strong&gt; provide a way for notifications to be delivered to an external web server whenever certain actions occur on a repository or organization. … For example, you can configure a webhook to execute whenever:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A repository is pushed to&lt;/li&gt;
&lt;li&gt;A pull request is opened&lt;/li&gt;
&lt;li&gt;A GitHub Pages site is built&lt;/li&gt;
&lt;li&gt;A new member is added to a team&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;defining-the-problem-and-solution&quot;&gt;Defining the problem and solution&lt;/h2&gt;
&lt;p&gt;As I said, my example will be automating the deployment of this site. Here is the normal workflow of me doing it manually:
&lt;img src=&quot;/assets/images/gh-actions-and-webhooks/workflow.png&quot; alt=&quot;My workflow&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the only place where my work is really required is writing the post. Other two steps can be automated. We will use GitHub Actions to generate the site content and Webhooks to let our server know about the new content so it can pull the changes. Lets get started.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-github-actions&quot;&gt;Setting up GitHub Actions&lt;/h3&gt;
&lt;p&gt;Setting up a GitHub Action is as easy as creating a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.yml&lt;/code&gt; file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/&lt;/code&gt; directory in your repository. Let us create a new action to build our site. Fortunately, there is already a &lt;a href=&quot;https://github.com/marketplace/actions/jekyll-actions&quot;&gt;GitHub action&lt;/a&gt; to do it for us. Create a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/jekyll.yml&lt;/code&gt; in your root directory of your repository and put the following contents:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Jekyll site CI&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ubuntu-latest&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;actions/checkout@v2&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Jekyll Actions&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;helaili/jekyll-action@2.2.0&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;keep_history&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;target_branch&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;gh-pages'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Thats it! We have created our first Action. When we push this change, GitHub will start building our site and push the result to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; branch. Currently, it will take a while to build because we dont use caching. So lets include it to build faster. Add the following piece as a second step:&lt;/p&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Use GitHub Actions' cache to shorten build times and decrease load on servers&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;actions/cache@v2&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vendor/bundle&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${{ runner.os }}-gems-${{ hashFiles('**/Gemfile') }}&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;restore-keys&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;${{ runner.os }}-gems-&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We are done with the Actions part. You can see the final code &lt;a href=&quot;https://github.com/sahinakkaya/sahinakkayadotdev/blob/main/.github/workflows/jekyll.yml&quot;&gt;here&lt;/a&gt;. When you are also done with the code, just push it to trigger the action.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-the-webhook-and-related-endpoint&quot;&gt;Setting up the Webhook and related endpoint&lt;/h3&gt;
&lt;p&gt;Now that we set up our Action to build the site, we need to let our server know about the changes so that it can pull the changes.&lt;/p&gt;
&lt;h4 id=&quot;creating-a-webhook-from-github&quot;&gt;Creating a Webhook from GitHub&lt;/h4&gt;
&lt;p&gt;To add a Webhook, open your repository in browser and navigate to &lt;em&gt;Settings &amp;gt; Webhooks&lt;/em&gt; and click &lt;em&gt;Add Webhook&lt;/em&gt;. Fill in the form with appropriate values. Here is an example:
&lt;img src=&quot;/assets/images/gh-actions-and-webhooks/add-webhook.png&quot; alt=&quot;Webhook form example&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This is all you have to do from GitHub. Now, whenever there is a &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt;&lt;/em&gt; event to your repository, GitHub will send a POST request to your &lt;em&gt;payload url&lt;/em&gt; with the details.&lt;/p&gt;
&lt;p class=&quot;notice--info&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; Our Action is configured to push to a branch in our repository, so it will also trigger this hook and we will catch it.&lt;/p&gt;
&lt;h4 id=&quot;creating-an-endpoint-to-handle-the-requests&quot;&gt;Creating an endpoint to handle the requests&lt;/h4&gt;
&lt;p&gt;I will use &lt;a href=&quot;https://flask.palletsprojects.com/en/2.0.x/&quot;&gt;Flask&lt;/a&gt; framework to handle the post requests coming to our endpoint. You can use whatever programming language or framework you want. It will be very simple code with just one job: Validate the secret keys and run a specific code.&lt;/p&gt;
&lt;p&gt;Lets start by creating a new project and a virtual environment:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mdkir post_receiver
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;post_receiver
python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; venv venv
&lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Install the required packages:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;Flask gunicorn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Create a new file for storing our environment variables:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# config.py
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;APP_KEY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;your-secret-key&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# same key that is used in github while creating the webhook
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROJECT_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/path/to/your/project/&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# you will want to cd into this path and perform commands such as git pull etc.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And create the Flask application:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# post_receiver.py
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;hashlib&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;hmac&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;subprocess&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;config&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'GET'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'POST'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'GET'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'OK'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'POST'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;APP_KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'utf-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;digester&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hmac&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashlib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sha256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;calculated_signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'sha256='&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hexdigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;actual_signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'X-Hub-Signature-256'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculated_signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual_signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Popen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'./perform-git-pull.sh'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROJECT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'OK'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Error'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'0.0.0.0'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I will not go into details explaining what each line does. Basically, we are checking if the request is a POST request and if so we are comparing the secret keys to make sure that the request is coming from GitHub. In our case, this is not too important because when the keys match we are running simple git commands in our repository but you might need it if you are doing something more complicated. And here is the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perform-git-pull.sh&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
git checkout gh-pages
git pull
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We are almost done! All we need to do is create a service to automatically run our code and let nginx handle our endpoint correctly.&lt;/p&gt;
&lt;p&gt;Create a new file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post_receiver.service&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd/system/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#/etc/systemd/system/post_receiver.service
# change &amp;lt;user&amp;gt; to your actual username
[Unit]
Description=post_receiver
After=network.target multi-user.target
[Service]
User=&amp;lt;user&amp;gt;
Environment=&quot;PYTHONPATH=/home/&amp;lt;user&amp;gt;/post_receiver/venv/bin/python&quot;
WorkingDirectory=/home/&amp;lt;user&amp;gt;/post_receiver
ExecStart=/home/&amp;lt;user&amp;gt;/post_receiver/venv/bin/gunicorn -b 127.0.0.1:5000 -w 2 --log-file /home/&amp;lt;user&amp;gt;/post_receiver/post_receiver.log post_receiver
[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Make sure port &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5000&lt;/code&gt; is reachable from outside.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;ufw allow 5000
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;ufw &lt;span class=&quot;nb&quot;&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Finally, edit your nginx configuration, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/sites-available/yoursite&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location = /postreceive/ {
proxy_pass http://localhost:5000/;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Start, restart the services&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start post_receiver
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;post_receiver
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Thats it! &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl https://yourdomain.com/postreceive/&lt;/code&gt; should return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;OK&quot;&lt;/code&gt; and we are ready to accept POST requests from GitHub.&lt;/p&gt;
&lt;h3 id=&quot;notes-for-debugging&quot;&gt;Notes for debugging&lt;/h3&gt;
&lt;p&gt;In case anything goes wrong, here are a few tips to debug:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every GitHub Action produces a log that you can examine. Check them to see if anything is odd.&lt;/li&gt;
&lt;li&gt;In the &lt;em&gt;Webhooks&lt;/em&gt; tab, there is a sub-tab called &lt;em&gt;Recent Deliveries&lt;/em&gt;. You can take a look at there to see the results of the requests from your hooks.&lt;/li&gt;
&lt;li&gt;You can always test your code locally with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;:
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; curl -i -X POST -H 'Content-Type: application/json' -d '{&quot;foo&quot;: &quot;bar&quot;, &quot;bar&quot;: &quot;baz&quot;}' https://yourdomain.com/postreceive/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;</content><author><name>Şahin Akkaya</name></author><category term="github-actions" /><category term="github-webhooks" /><category term="ci-cd" /><summary type="html">In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of this site but you can do whatever you want. Just understanding the basics will be enough.</summary></entry><entry><title type="html">Stop cat-pipeing, You Are Doing It Wrong!</title><link href="https://sahinakkaya.dev/2022/01/01/stop-cat-pipeing.html" rel="alternate" type="text/html" title="Stop cat-pipeing, You Are Doing It Wrong!" /><published>2022-01-01T15:00:00+00:00</published><updated>2022-01-01T15:00:00+00:00</updated><id>https://sahinakkaya.dev/2022/01/01/stop-cat-pipeing</id><content type="html" xml:base="https://sahinakkaya.dev/2022/01/01/stop-cat-pipeing.html">&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;some_file | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;some_pattern
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Im sure that you run a command something like above at least once if you are using terminal. You know how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; works and you also know what pipe (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didnt know is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; already accepts file as an argument. So the above command could be rewritten as:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;some_pattern some_file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;… which can make you save a few keystrokes and a few nanoseconds of CPU cycles. Phew! Not a big deal if you are not working files that contains GBs of data, right? I agree but you should still use the latter command because it will help you solve some other problems better. Here is a real life scenario: You want to search for some specific pattern in all the files in a directory.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you use the first approach, you may end up running commands like this:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
 config.lua  Git.lua  init.lua  markdown.lua  palette.lua  util.lua
 diff.lua  highlights.lua  LSP.lua  Notify.lua  Treesitter.lua  Whichkey.lua
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;config.lua | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;light
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;diff.lua | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;light
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;Git.lua | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;light
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;highlights.lua | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;light
Pmenu &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.popup_back &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
CursorLineNr &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, style &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bold&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
Search &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.search_blue &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
IncSearch &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.search_blue &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;init.lua | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;light
&lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;highlights &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; require &lt;span class=&quot;s2&quot;&gt;&quot;onedarker.highlights&quot;&lt;/span&gt;
highlights,
&lt;span class=&quot;c&quot;&gt;# You still have a lot to do :/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;If you use the second approach, you will immediately realize that you can send all the files with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; operator and you will finish the job with just one command (2 if you include mandatory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; :D):&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
 config.lua  Git.lua  init.lua  markdown.lua  palette.lua  util.lua
 diff.lua  highlights.lua  LSP.lua  Notify.lua  Treesitter.lua  Whichkey.lua
&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;light &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
highlights.lua: Pmenu &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.popup_back &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
highlights.lua: CursorLineNr &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, style &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bold&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
highlights.lua: Search &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.search_blue &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
highlights.lua: IncSearch &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.search_blue &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
init.lua:local highlights &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; require &lt;span class=&quot;s2&quot;&gt;&quot;onedarker.highlights&quot;&lt;/span&gt;
init.lua: highlights,
LSP.lua: NvimTreeNormal &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.alt_bg &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
LSP.lua: LirFloatNormal &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray, &lt;span class=&quot;nb&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.alt_bg &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
markdown.lua: markdownIdDelimiter &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
markdown.lua: markdownLinkDelimiter &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; C.light_gray &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
palette.lua: light_gray &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#abb2bf&quot;&lt;/span&gt;,
palette.lua: light_red &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#be5046&quot;&lt;/span&gt;,
util.lua:local &lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;highlight&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;group, properties&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
util.lua: &lt;span class=&quot;s2&quot;&gt;&quot;highlight&quot;&lt;/span&gt;,
util.lua: highlight&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;group, properties&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Isnt this neat? You might say that &lt;em&gt;“This is cheating! You are using a wild card, of course it will be easier.”&lt;/em&gt; Well, yes. Technically I could use the same wild card in the first command like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat * | grep light&lt;/code&gt; but:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I figured that out only after using wild card in the second command. So I think it is does not feel natural.&lt;/li&gt;
&lt;li&gt;It is still not giving the same output. Try and see the difference! &lt;a href=&quot;##&quot; title=&quot;You will not be able to see which file contains which line. 'cat' will just concatenate all the input.&quot;&gt;*&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Şahin Akkaya</name></author><category term="cat" /><category term="grep" /><category term="linux" /><category term="command-line" /><summary type="html">cat some_file | grep some_pattern Im sure that you run a command something like above at least once if you are using terminal. You know how cat and grep works and you also know what pipe (|) does. So you naturally combine all of these to make the job done. I was also doing it this way. What I didnt know is that grep already accepts file as an argument. So the above command could be rewritten as: grep some_pattern some_file</summary></entry></feed>

869
index.html 100644
View File

@ -0,0 +1,869 @@
<!DOCTYPE html>
<!--
Minimal Mistakes Jekyll Theme 4.24.0 by Michael Rose
Copyright 2013-2020 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
--><html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<!-- begin _includes/seo.html --><title>Şahin Akkaya's Personal Page</title>
<meta name="description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<meta name="author" content="Şahin Akkaya">
<meta property="og:type" content="website">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Şahin Akkaya's Personal Page">
<meta property="og:title" content="Şahin Akkayas Personal Page">
<meta property="og:url" content="https://sahinakkaya.dev/">
<meta property="og:description" content="Şahin Akkayas personal blog - a perfectionist who likes to tinker everything until it is just right. Get ready to find some sweet tips that will boost your productivity and make you fall in love with your computer.">
<link rel="canonical" href="https://sahinakkaya.dev/">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": null,
"url": "https://sahinakkaya.dev/"
}
</script>
<!-- end _includes/seo.html -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Şahin Akkaya's Personal Page Feed">
<!-- https://t.co/dKP3o1e -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"></noscript>
<!-- start custom head snippets -->
<!-- insert favicons. use https://realfavicongenerator.net/ -->
<!-- end custom head snippets -->
</head>
<body class="layout--home">
<nav class="skip-links">
<ul>
<li><a href="#site-nav" class="screen-reader-shortcut">Skip to primary navigation</a></li>
<li><a href="#main" class="screen-reader-shortcut">Skip to content</a></li>
<li><a href="#footer" class="screen-reader-shortcut">Skip to footer</a></li>
</ul>
</nav>
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title" href="/">
/home/sahin/
</a>
<ul class="visible-links">
<li class="masthead__menu-item">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item">
<a href="/about/">About</a>
</li>
<li class="masthead__menu-item">
<a href="/contact/">Contact</a>
</li>
</ul>
<button class="search__toggle" type="button">
<span class="visually-hidden">Toggle search</span>
<i class="fas fa-search"></i>
</button>
<button class="greedy-nav__toggle hidden" type="button">
<span class="visually-hidden">Toggle menu</span>
<div class="navicon"></div>
</button>
<ul class="hidden-links hidden"></ul>
</nav>
</div>
</div>
</div>
<div class="initial-content">
<div id="main" role="main">
<div class="sidebar sticky">
<div itemscope itemtype="https://schema.org/Person">
<div class="author__avatar">
<img src="/assets/images/logo.jpg" alt="Şahin Akkaya" itemprop="image">
</div>
<div class="author__content">
<h3 class="author__name" itemprop="name">Şahin Akkaya</h3>
<div class="author__bio" itemprop="description">
<p>A perfectionist who likes to tinker everything until it is just right.</p>
</div>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li itemprop="homeLocation" itemscope itemtype="https://schema.org/Place">
<i class="fas fa-fw fa-map-marker-alt" aria-hidden="true"></i> <span itemprop="name">Istanbul, Turkey</span>
</li>
<li><a href="https://github.com/sahinakkaya" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-github" aria-hidden="true"></i><span class="label">sahinakkayadev</span></a></li>
<li><a href="https://stackoverflow.com/users/9608759" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-stack-overflow" aria-hidden="true"></i><span class="label">Asocia</span></a></li>
<li><a href="https://twitter.com/sahinakkayadev" rel="nofollow noopener noreferrer"><i class="fab fa-fw fa-twitter-square" aria-hidden="true"></i><span class="label">@sahinakkayadev</span></a></li>
<li><a href="mailto:sahin@sahinakkaya.dev" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-envelope" aria-hidden="true"></i><span class="label">sahin@sahinakkaya.dev</span></a></li>
<li><a href="/assets/docs/resume.pdf" rel="nofollow noopener noreferrer"><i class="fas fa-fw fa-id-card" aria-hidden="true"></i><span class="label">Resume</span></a></li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs" rel="nofollow noopener noreferrer">
<i class="fas fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<div class="archive">
<h1 id="page-title" class="page__title"></h1>
<h3 class="archive__subtitle">Recent Posts</h3>
<div class="entries-list">
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2023/01/15/hot-reloading-with-trap-and-kill.html" rel="permalink">Hot-Reload Long Running Shell Scripts (feat. trap / kill)
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2023-01-15T21:48:08+00:00">January 15, 2023</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">trap them and kill them!
There is a beautiful command in Linux called trap which traps signals and let you run specific commands when they invoked. There is ...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/12/29/recap-of-2022.html" rel="permalink">Recap of 2022
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-12-29T20:22:08+00:00">December 29, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Its been a while… It has been so long that I forgot how I was writing my blogs back then. My life didnt change that much. Actually, it is getting worse.
</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/06/22/rant-on-peoples-reaction-to-copilot.html" rel="permalink">Rant: Stop whatever you are doing and learn how licenses work
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-06-22T07:46:00+00:00">June 22, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Recently, Github announced
that they are making Github Copilot available for everyone. Previously, it was in Beta and you could get it through the waiting l...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/04/08/confession-time.html" rel="permalink">Confession Time
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-04-08T15:46:00+00:00">April 8, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">A failure story
Last week, I received an email from Lets Encrypt reminding me to renew my certificates. I forgot to renew it and the certificate expired. No...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/03/03/never-get-trapped-in-grub-rescue-again.html" rel="permalink">Never Get Trapped in Grub Rescue Again!
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-03-03T00:46:00+00:00">March 3, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
4 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Anytime I install a new system on my machine, I pray God for nothing bad happens. But it usually happens. When I reboot, I find myself in the “Grub rescue” m...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/02/27/creating-a-useless-user.html" rel="permalink">Creating a <em>Useless</em> User
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-02-27T13:40:00+00:00">February 27, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Story
In my previous post, I explained how to do port forwarding to access some machine behind private network. I will use this method to fix some issues in ...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/02/26/ssh-into-machine-that-is-behind-private-network.html" rel="permalink">SSH into Machine That Is Behind a Private Network
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-02-26T21:40:00+00:00">February 26, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Story
I believe there is always a “tech support person” in every home. Everyone knows that when there is a problem with any electronic device, they should as...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/01/21/ffmpeg-to-rescue.html" rel="permalink">Using ffmpeg for Simple Video Editing
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-01-21T20:40:00+00:00">January 21, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
1 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Story
Today, I have recorded a video for one of my classes and I was required to upload it till midnight. The video was perfect except for a few seconds wher...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/01/04/build-and-deploy-automatically.html" rel="permalink">Automatically Build and Deploy Your Site using GitHub Actions and Webhooks
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-01-04T17:40:00+00:00">January 4, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
5 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">In this post I will explain how you can use GitHub to automate the build and deployment processes that you have. I am going to automate the deployment of thi...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2022/01/01/stop-cat-pipeing.html" rel="permalink">Stop cat-pipeing, You Are Doing It Wrong!
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2022-01-01T15:00:00+00:00">January 1, 2022</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
2 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">cat some_file | grep some_pattern
Im sure that you run a command something like above at least once if you are using terminal. You know how cat and grep wo...</p>
</article>
</div>
<div class="list__item">
<article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork">
<h2 class="archive__item-title no_toc" itemprop="headline">
<a href="/2021/12/24/first-blog-post.html" rel="permalink">First blog post
</a>
</h2>
<p class="page__meta">
<span class="page__meta-date">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
<time datetime="2021-12-24T23:54:08+00:00">December 24, 2021</time>
</span>
<span class="page__meta-sep"></span>
<span class="page__meta-readtime">
<i class="far fa-clock" aria-hidden="true"></i>
3 minute read
</span>
</p>
<p class="archive__item-excerpt" itemprop="description">Hello, World!* So here I am and welcome to my first blog. Having a personal space on the Internet has been a dream for me for years and I am happy that it fi…
</p>
</article>
</div>
</div>
</div>
</div>
</div>
<div class="search-content">
<div class="search-content__inner-wrap">
<form class="search-content__form" onkeydown="return event.key != 'Enter';">
<label class="sr-only" for="search">
Enter your search term...
</label>
<input type="search" id="search" class="search-input" tabindex="-1" placeholder="Enter your search term...">
</form>
<div id="results" class="results"></div>
</div>
</div>
<div id="footer" class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="page__footer-follow">
<ul class="social-icons">
<li><a href="/feed.xml"><i class="fas fa-fw fa-rss-square" aria-hidden="true"></i> Feed</a></li>
</ul>
</div>
<div class="page__footer-copyright">© 2023 Şahin Akkaya's Personal Page. Powered by <a href="https://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div class="page__footer-copyright">
Check out the <a href="https://github.com/Asocia/sahinakkayadotdev">code</a> of this site.
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script src="/assets/js/lunr/lunr.min.js"></script>
<script src="/assets/js/lunr/lunr-store.js"></script>
<script src="/assets/js/lunr/lunr-en.js"></script>
</body>
</html>

View File

@ -1,7 +0,0 @@
---
# Feel free to add content and custom Front Matter to this file.
# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
layout: home
---

1
robots.txt 100644
View File

@ -0,0 +1 @@
Sitemap: https://sahinakkaya.dev/sitemap.xml

60
sitemap.xml 100644
View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://sahinakkaya.dev/2021/12/24/first-blog-post.html</loc>
<lastmod>2021-12-24T23:54:08+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/01/01/stop-cat-pipeing.html</loc>
<lastmod>2022-01-01T15:00:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/01/04/build-and-deploy-automatically.html</loc>
<lastmod>2022-01-04T17:40:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/01/21/ffmpeg-to-rescue.html</loc>
<lastmod>2022-01-21T20:40:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/02/26/ssh-into-machine-that-is-behind-private-network.html</loc>
<lastmod>2022-02-26T21:40:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/02/27/creating-a-useless-user.html</loc>
<lastmod>2022-02-27T13:40:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/03/03/never-get-trapped-in-grub-rescue-again.html</loc>
<lastmod>2022-03-03T00:46:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/04/08/confession-time.html</loc>
<lastmod>2022-04-13T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/06/22/rant-on-peoples-reaction-to-copilot.html</loc>
<lastmod>2022-06-22T07:46:00+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2022/12/29/recap-of-2022.html</loc>
<lastmod>2022-12-29T20:22:08+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/2023/01/15/hot-reloading-with-trap-and-kill.html</loc>
<lastmod>2023-01-15T21:48:08+00:00</lastmod>
</url>
<url>
<loc>https://sahinakkaya.dev/about/</loc>
</url>
<url>
<loc>https://sahinakkaya.dev/contact/</loc>
</url>
<url>
<loc>https://sahinakkaya.dev/</loc>
</url>
<url>
<loc>https://sahinakkaya.dev/assets/docs/resume.pdf</loc>
<lastmod>2023-02-14T08:58:46+00:00</lastmod>
</url>
</urlset>