"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 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*. 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*. 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*. 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**. 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 RSS Feed 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! ","categories":[],
"excerpt":"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: 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: ❯ 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): ❯ 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! * ","categories":[],
"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 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. 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: 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 is the first result: 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! ","categories":[],
"excerpt":"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, localtunnel 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. # 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. # 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. 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 ","categories":[],
"excerpt":"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 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. 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. ❯ 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. ❯ 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 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! ","categories":[],
"excerpt":"A failure story Last week, I received an email from Let’s Encrypt 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 ","categories":[],
"excerpt":"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. 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 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. ","categories":[],
"excerpt":"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! 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. ","categories":[],
"excerpt":"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! Basic Example Let’s start by creating something very simple and build up from there. Create a script with the following contents: #!/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: ❯ 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. ❯ 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. #!/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: ❯ ./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! * This command is awesome. Without further ado, let’s get started. Create a script called script1 with the following contents: #!/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: ❯ chmod +x script1 ❯ ln -s script1 script2 Now we can pretend they are two different scripts as their outputs differ: ❯ ./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: #!/bin/bash echo \"My pid is $$. You know what to do ( ͡° ͜ʖ ͡°)\" echo \"You can also kill me with 'kill -s INT \\`pgrep `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\" kill \"$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 # killing this pid will end all the grandchilds. # (useful if you have pipes (|) or other &'s in your script!) ($script) & pids+=(\"$!\")