Keep learning forward
To be updated ...#TIL : The safest way to reset root password of MySQL Server
When you get stucked in this error message "Access denied for user 'root@localhost' ...", you search the way to reset the root password on the Internet, but life is Hard ! (No answer makes you feel it's right way, even some do not work)
So to solve this problem, we need to understand MySQL Authentication
Step 1 : Disable MySQL Authentication by skip loading grant-tables on loading MySQL server
Open MySQL server config file, it might be in /etc/mysql/mysql.conf.d/mysqld.cnf. Add this line to section
mysql
[mysqld] skip-grant-tables
DANGER : BE CAREFULL ! AFTER RESETTING SERVER, YOUR MYSQL SERVER ALLOWS ANY CONNECTION FROM ANY USER FROM ANY HOST BY ANY PASSWORD
So safe way is to make sure that you are the only one connect MySQL, by
- change to listening port of the server
[mysqld] skip-grant-tables port=6033 bind-address = 127.0.0.1
- disable access through MySQL socket
$ sudo chmod 400 /var/run/mysqld/mysqld.sock
Step 2 : Restart the MySQL server
$ sudo systemctl restart mysql
Step 3 : Connect to mysql server by mysql cli, now you can connect free
$ mysql -h 127.0.0.1 -P 6033
Step 4 : Analyze mysql.user table
mysql> use mysql Database changed mysql> select Host, User, plugin, password_expired, account_locked from user where User = 'root'; +-----------+------------------+-----------------------+------------------+----------------+ | Host | User | plugin | password_expired | account_locked | +-----------+------------------+-----------------------+------------------+----------------+ | % | root | mysql_native_password | N | N | +-----------+------------------+-----------------------+------------------+----------------+ 4 rows in set (0.00 sec)
These fields meaning :
- Host : allowed client host name or IP address
127.0.0.1
: allow local clients connect via TCPlocalhost
: allow local clients connect via local UNIX socket file/var/run/mysqld/mysqld.sock
%
: any wildcard, allow from all hosts
- User : allowed user name
root
: allow root user
- plugin :
mysql_native_password
: use hashing function of MySQLPASSWORD('YOURPASSWORD')
, stored inauthentication_string
field (MySQL 5.7+) orpassword
field (MySQL 5.6 or older)auth_socket
: use socket
- password_expired :
Y
: password is expiredN
: password is not expired (still working)
- account_locked :
Y
: account is lockedN
: account is not locked (still working)
Step 5 : Reset your password
Rewrite your sql command by replacing
NEWPASSWORD
and WHERE statement to match account we analyze in Step 4MySQL 5.7+
mysql> update user set plugin = 'mysql_native_password', authentication_string = PASSWORD('NEWPASSWORD'), password_expired = 'N', account_locked = 'N' where Host = '%' and User = 'root';
MySQL 5.6 or older
mysql> update user set plugin = 'mysql_native_password', password = PASSWORD('NEWPASSWORD'), password_expired = 'N', account_locked = 'N' where Host = '%' and User = 'root';
Make sure that we changed 1 row by checking the result log : Query OK, 1 rows affected (0.00 sec)
Step 6 : Flushing privileges
mysql> flush privileges; mysql> quit;
Step 7 : Rollback all config changes
Update your mysql server config file, make sure to comment out
skip-grant-tables
[mysqld] # skip-grant-tables port=3306 bind-address = 127.0.0.1
$ sudo systemctl restart mysql
Trying to connect to MySQL server with your new password
$ mysql -u root -h 127.0.0.1 -p
If anything works perfectly, last step is enabling access to socket file
$ sudo chmod 777 /var/run/mysqld/mysqld.sock
HOPE IT HELP ! WE SOLVE PROBLEMS BY UNDERSTANDING IT !
#TIL : Curl override Name Resolution with specific IP address
You can overrride the Name Resolution with specific IP address without adding the hostname to /etc/hosts file by using
--resolve
option.Syntax :
--resolve <host:port:address>
It will resolve IP address when connect to host on port
Example :
This will connect 127.0.0.1
$ curl --resolve google.com:80:127.0.0.1 "http://google.com/"
But this won't connect 127.0.0.1, because we use 443 port for https
$ curl --resolve google.com:80:127.0.0.1 "https://google.com/"
For cover all ports, use
*
wildcard$ curl --resolve google.com:*:127.0.0.1 "https://google.com/"
#TIL : Curl extract info from verbose mode
Curl is great tool to do thing with HTTP in command line interface. Sometimes your want to get extra info from HTTP response and put in a variable. Here is the way :
Using
--write-out
is magical option help you to write out all info you want, or put it in a variable.Example :
$ code=$(curl --write-out %{response_code} --silent --output /dev/null https://khanhicetea.com) $ echo $code # get http response status code 200
$ tracetime=$(curl --write-out "%{time_namelookup} %{time_connect} %{time_appconnect} %{time_pretransfer} %{time_redirect} %{time_starttransfer} %{time_total}" --silent --output /dev/null https://khanhicetea.com) $ echo $tracetime # Trace all timing of http connection (in seconds) 0.068 0.097 0.370 0.370 0.000 0.720 0.721
Use case :
Below code is cron bash script that checks if http response code equals :
- 502 (Bad Gateway), then restart the backend server (nginx -> apache2)
- not 200 then restart the frontend server (nginx)
#!/bin/bash code=$(curl --write-out %{response_code} --silent --output /dev/null http://example.com) [ $code -eq 502 ] && sudo systemctl restart httpd || echo "everything works fine" [ ! $code -eq 200 ] && sudo systemctl restart nginx || echo "everything works fine"
More info variables, you can check it here
#TIL : Internal Variables in BASH
$PWD
Your current working directory, so you don't have to use
CWD=$(pwd)
$OLDPWD
Your previous working directory
Note : You can jump directly to it by the command
cd -
$SECONDS
The number of seconds the script has been running
You can use it for profiling or limiting timeout
TIME_LIMIT=60 START=$SECONDS while [ $(($SECONDS - START)) -le "$TIME_LIMIT" ] do ## Your work here done echo "It takes $SECONDS seconds to get here !"
$RANDOM
Get random integer number, for getting random name or just roll a dice ;)
#TIL : Setter and getter behavior of class property in Python3
In previous TIL, I learned about the way to define getter and setter in Javascript
Today, I learned it in Pythonic way ;) (in Python3)
So here is example (the easy way to learn from a code) :
class A: def __init__(self,x): print ('init', x) self.x = x @property def x(self): print ('getter') return self.__x @x.setter def x(self, x): print ('setter', x) if x < 0: self.__x = 0 elif x % 2 == 0: self.__x = x else: self.__x = x * 2 a = A(10) print(a.x) a.x = -1 print(a.x) a.x = 2 print(a.x) a.x = 7 print(a.x)
Output :
init 10 setter 10 getter 10 setter -1 getter 0 setter 2 getter 2 setter 7 getter 14
This is so cool feature, and even it has
deleter
property method, which triggers when we rundel object.property
:DIn reactive JS framework that they use getter and setter like a core of Reactive, let find out more next articles ;)
#TIL : SQL Wildcard Characters
SQL databases support 2 main wildcards :
%
: represents zero, one, or multiple characters_
: represents a single character
#TIL : Do not use mutable objects as default parameters
I learned this from learn-python3
Example :
def append_if_multiple_of_five(number, magical_list=[]): if number % 5 == 0: magical_list.append(number) return magical_list print(append_if_multiple_of_five(100)) print(append_if_multiple_of_five(105)) print(append_if_multiple_of_five(123)) print(append_if_multiple_of_five(123, [])) print(append_if_multiple_of_five(123))
Result :
[100] [100, 105] [100, 105] [] [100, 105]
So default parameters in Python are shared between function calls if it isn't passed from caller. So be careful because shared mutable object can affect your logic between function calls, where MAGIC was born !
One safe way to achieve the goal, use
None
as replacement like thisdef append_if_multiple_of_five(number, magical_list=None): if not magical_list: magical_list = [] if number % 5 == 0: magical_list.append(number) return magical_list print(append_if_multiple_of_five(100)) print(append_if_multiple_of_five(105)) print(append_if_multiple_of_five(123)) print(append_if_multiple_of_five(123, [])) print(append_if_multiple_of_five(123))
Result :
[100] [105] [] [] []
#TIL : Context Managers in Python
In Python, sometimes you will see this syntax
with something: do_something_else(something)
Then you ask yourself, why I have to use this
with
syntax ? What runs inside that statement ?Here is how it works, it's called Context Managers in object
You can define context managers for a class of object to make sure some logic runs correctly without forgeting
Example :
class Animal: def __init__(self, name): self.name = name def __enter__(self): print("Enter the room !") def __exit__(self, exc_type, exc_value, traceback): print("Exit the room !") kitty = Animal("Kitty Kat") with kitty: print(kitty.name)
Result
Enter the room ! Kitty Kat Exit the room !
So, when you start using
with
keyword on a object, it runs__enter__
method, when everything insidewith
block is runned,__exit__
will be called !It's cool feature of Python !
#TIL : Running git command using another ssh key
Sometimes you want to use another private key to authorize to remote repository.
Just add an environment variable before the command you wanna run :
GIT_SSH_COMMAND='ssh -i [your-private-key]
Example :
$ GIT_SSH_COMMAND='ssh -i ~/keys/key1' git pull
#TIL : Put .git data outside project directory
Sometimes you want to put .git data into outside directory (to use another disk partition or to protect your git data). Use
--separate-git-dir=
option to get that.Example :
$ git init --separate-git-dir=/var/gitstorage/myproject
Bonus : to protect .git data from other users, use this option
--shared
within octal value (same tochmod
)Example : this will protect git file from writing by group and reading/writing by others
$ git init --separate-git-dir=/var/gitstorage/myproject --shared=0640
#TIL : Reuse cookies between multi requests in Curl tool
Curl is good lib and tool to simulate HTTP requests. One common usecase is reusing the cookies between 2 or more requests. So you don't have to copied last "Set-Cookie" of previous response then paste it to "Cookie" of next request.
To achieve that, you have to use a cookie jar (sounds fun) to store cookies then use that cookie jar in next request. We have two parameters :
-c [cookie_jar_file] : store response cookies in a file
-b [cookie_jar_file] : getting cookies from cookie jar file then send it in request
Combine them together we can simulate a real browser HTTP requests easily.
Example :
$ curl -c cookies.txt -b cookies.txt -XPOST -d "user=admin&password=hahahehe" http://example.com/login ...... $ curl -c cookies.txt -b cookies.txt -XGET http://example.com/dashboard Hello admin !
#TIL : Encrypt and decrypt file using openssl command line
You can encrypt and decrypt the file using openssl command line. Somehow you will need to encrypt your important file with a secret key.
Encrypt
openssl enc -aes-256-cbc -in [input_file] -out [output_file]
Then Enter 2 times your secret key (this should be hard to guess and don't loose it)
Decrypt
openssl enc -aes-256-cbc -d -in [input_file] > [output_file]
Then enter your secret key to decrypt the content !
Notice : should use a 10-char length secret with alpha nums and special characters
#TIL : Get random number from computer
Today, I read my junior team-mate code and find this line
$number = rand(2,1000)*rand(2,1000);
This made me remember that's same idea of my own in many years ago. Then I ask myself, is it good to generate a random number from 2 random numbers ?
So the main reason that he wrote this was making probability of same number at same time must be low. We can know that this will return a random number from 4 to 1000000. So why don't we just do this ?
$number = rand(4,1000000);
This function will make probability lower than above function, because above function is commutative (AB = BA). So stay away from commutative function (
+
,*
) when generate a random number.Need more powerful ? Try Pseudorandom Number Generator (PRNG) !!
#TIL : View DNS history of a domain
You can check the history of a domain (A Record). It's useful in case you forgot the old IP of domain.
Check it here : http://viewdns.info/iphistory/
Example : this is Github A record history http://viewdns.info/iphistory/?domain=github.com
#TIL : Never autostart XDebug in cli environment
TLDR;
Never ever enable xdebug.remote_autostart in cli
Xdebug is handy extension helps you debug your PHP code. But it slows the performance in cli mode, especially run PHP cli tool like composer or phpunit.
So please disable Xdebug in cli mode or set
xdebug.remote_autostart=0
in INI file.#TIL : try, catch and finally in PHP
We have to deal with exceptions every moment we touch PHP web development, and so please be carefully with running order of exception catching.
Here is an example
<?php function a() { try { throw new Exception('dsads'); } catch (Exception $e) { return 'b'; } finally { echo 'c'; } } echo a();
Then the output is
cb
Than mean even
return 'b';
runs, the finally code must be runned before function result passes out.#TIL : Use temporarily data from another database in SQLite
Sometimes, we need to use temporarily data from another database file. There is simple and fast way to achieve that without transfering data from file X to file Y.
We connect to main database
$ sqlite3 main.sqlite
Then using the ATTACH command to attach another database as an alias in main database
> ATTACH another_db.sqlite as TEMP;
Let listing the tables
> .tables TEMP.users TEMP.posts users admins categories
As you can see, we got a list of tables, which are prefixed by defined alias
TEMP
we used in ATTACH command. So you only need to use these tables as normal tables.Example of copying data between 2 tables (same structure) :
> INSERT INTO users SELECT * FROM TEMP.users;
#TIL : Exporting environment variables on virtual env activate
You can put common environment variables to the file
venv/bin/activate
. So everytime we active the virtual env, everything is on the way# venv/bin/active content # export your env vars here export FLASK_APP=hello export FLASK_ENV=development export DATABASE=hello.sqlite3 export SECRET_KEY=secret_key_here
#TIL : Setup wildcard domains .test for development in MacOS
Too tired of setting your local domain each time you create new virtual development domain, etc helloworld.test, unit.test point to 127.0.0.1
There is a better way to achieve that by using dnsmasq, then set up a wildcard domains for development. In this case I use .test because .dev has been owned by Google and they strictly use HTTPS in mainly browsers.
Install dnsmasq
$ brew install dnsmasq
Adding .test wildcard to config file
$ echo 'address=/.test/127.0.0.1' > $(brew --prefix)/etc/dnsmasq.conf
Setup dnsmasq as a startup service
$ sudo brew services start dnsmasq
Then add
127.0.0.1
(dnsmasq IP) as first DNS resolverSystem Preferences > Network > Wi-Fi > Advanced... > DNS > add 127.0.0.1 > move it to top of the list.
Checking everything is worked by listing all resolvers
$ scutil --dns
Try it out
$ nslookup -type=a something.test $ ping helloworld.test
#TIL : Send a file through networking via netcat
If you're working on 2 machines in same networking and want to send a file from machine A to machine B. But you don't have USB, floopy disk :lol: or insanse Bluetooth. There is simple way to send a file to another computer without setting up SSH or SMB (althrough these way are safer than it).
On the machine A (with IP address : 192.168.1.2)
$ cat data.txt | sudo nc -l 0.0.0.0 6666
On the machine B
$ nc 192.168.1.2 6666 > here_the_data.txt
Have fun playing net😼 !! ;)
#TIL : Create tiny chat channel via netcat
In a network, you can create a tiny chatting channel using netcat. It's lightweight TCP protocol with plain-text transmission, so be carefully on using.
First, create a channel by picking port number (ex: 7777)
$ sudo nc -l 0.0.0.0 7777
Then, tell you friend your IP and channel port. He will use this info to connect the channel
$ nc 192.168.1.2 7777
Finnally, start chatting !! Each message will be send when you press [Enter]
Note: End the session by press
Ctrl + D
#TIL : Prepend line number to file
When you want to prepend line number in every line of file, use the
-n
flag ofcat
tool.Example :
cat -n a.txt
Or even from many file
cat -n a.txt b.txt c.txt
#TIL : Cut file content from line to line
In case you have a big file which contains a lot of content (2+ GB). And you only need a small part from the file (the part is continuous string from line X to line Y).
You have many ways to achieve that :
- Use
vi
editor and delete from line 1 to line (X-1) by press[X-1]dd
then go to line (Y-X+2) and delete to last line by pressdG
- Use
sed -n '[X][Y]p' [input_file] > [output_file]
. Example :sed -n '15,68p' a.sql > b.sql
- Use
head
andtail
trick :head -n[Y] [input_file] | tail -n[Y-X+1] > [output_file]
I personally recommend using the
sed
way, it's faster and simpler to remember.- Use
#TIL : Create a sequence of numbers
In the past, every time I want to create a sequence of numbers. I have to use something like MS EXCEL, then copy it and paste to text editor. It's tricky way and slow !
Now, I can use the handy tool
seq
to achieve thatman seq
SEQ(1) User Commands SEQ(1) NAME seq - print a sequence of numbers SYNOPSIS seq [OPTION]... LAST seq [OPTION]... FIRST LAST seq [OPTION]... FIRST INCREMENT LAST DESCRIPTION Print numbers from FIRST to LAST, in steps of INCREMENT. Mandatory arguments to long options are mandatory for short options too. -f, --format=FORMAT use printf style floating-point FORMAT -s, --separator=STRING use STRING to separate numbers (default: \n) -w, --equal-width equalize width by padding with leading zeroes
So we have 3 main arguments (same as for loop) :
- FIRST
- INCREMENT
- LAST
And 3 options :
- format : you can use string format like
This is number %g
- separetor : default is new line
- equal width : padding with leading zeroes
Example :
$ seq -f"This is number %g" 3 4 20 This is number 3 This is number 7 This is number 11 This is number 15 This is number 19
$ seq -w -s", " 10 01, 02, 03, 04, 05, 06, 07, 08, 09, 10
#TIL : Install CA root certificate on iOS device
Disclaimer : ⚠️ You can do it, but it's at your own risk !
Sometimes you want to accept a SSL firewall proxy or self-MITM proxy, the important step is installing its CA root certificate to your device. Because iOS apps almost use all https connections (that's new rule).
This is the way to install and enable custom CA Root cert :
- Step 1 : encode your certificate to binary-PEM (only need when you try
cat [ca-cert]
and see ASCII base64 characters)
openssl x509 -outform der -in [ca-cert] -out [new-ca-cert].crt
- Step 2 : Transfer the root certificate to your device (can use 1 of 2 methods : uploading cert to public webserver and open link in Safari app; or share certificate file through AirDrop - between 2 Apple devices).
Tips : use
ngrok
as a simple tunnel webserver if you don't have AirDrop supported PC.Step 3 : Click Install on install profile screen
Step 4 : Enable installed certificate, go to
Settings > General > About > Certificate Trust Settings
, then switch On your certificate item. (You could disable it when you don't need it)
;) Check the web connection !
- Step 1 : encode your certificate to binary-PEM (only need when you try
#TIL : Flush DNS cache on iOS device
There are 2 simple ways to clear DNS cache on iOS devices :
- (FASTER) Just enable the Airplane Mode, wait 10 seconds and disable it
- (SLOWER) Reboot the device ! ;) You know this always be classic answer for many questions :D
#TIL : Sending Cookie in AJAX CORs request
By default, browser will remove the cookie and authorization header from AJAX CORs request. So
before sending out the request, make surewithCredentials
must be true.In this case, CORs response must specify which origin is allowed (mean
no wildcard allowed origin rule).#TIL : Prevent source hacking from .git directory exposing
Many web project use Git as source version control tools. So in production
server, we could expose the hidden.git
directory - which contains all most
infomation about project source code.To "rip" a source code from a vulnerable website, we can use this tool : https://github.com/kost/dvcs-ripper#git
So to prevent this happens, try to deny all http access to hidden files and
directories (usually starts by.
character)Example of Nginx config
location ~ /\. { deny all; }
#TIL : Build lightweight image by using multistage
Docker is great tool to build a pull-n-run application. But sometimes, your image will be large if you build image from a big base image which has heavy compliling toolbox.
Ex:
One-stage build
FROM golang:1.9.2 WORKDIR /go/src/github.com/khanhicetea/test/ COPY . . RUN CGO_ENABLED=0 GOOS=linux go build . ENTRYPOINT ["/go/src/github.com/khanhicetea/test/test"]
Multi-stage builds
FROM golang:1.9.2 WORKDIR /go/src/github.com/khanhicetea/test/ COPY . . RUN CGO_ENABLED=0 GOOS=linux go build . FROM scratch COPY --from=0 /go/src/github.com/khanhicetea/test/test . ENTRYPOINT ["/test"]
So final image will only contains /test excutable file.
COPY --from=0
means COPY from build has index0
in Dockerfile.#TIL : List opening ports or listening UNIX sockets
In Linux, you can use
netstat
to list all opening ports and listening UNIX sockets$ sudo netstat -npl
Tip to remember command : network statistics - natual languge processing
;)