Tech Chorus

Access Dictionary Keys As Object Attributes

written by Sudheer Satyanarayana on 2015-02-24

You access Python dictionary keys using the syntax:

my_dicy[my_key]

For example:

>>> my_dict = {'food': 'idly'}
>>> my_dict['food']
'idly'

Sometimes, you might want to access the dictionary keys using:

my_dict.my_key

syntax. If you do this is what happens:

>>> my_dict.food
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'food'

How can you solve this? Easy.

 pip install attrdict

How do you use the newly installed package?

>>> from attrdict import AttrDict
>>> my_dict = AttrDict({'food': 'idly'})
>>> my_dict.food
'idly'

How to get Fedora to suspend laptop when lid is closed?

written by Sudheer Satyanarayana on 2015-02-24

Edit the file:

/etc/systemd/logind.conf

Look for the 'HandleLidSwitch' entry. Add the entry if it is not there already. If the entry is already there, change to:

HandleLidSwitch=hibernate

Then restart systemd-logind:

systemctl restart systemd-logind.service

This is tested on Fedora 21.

Pani

written by Sudheer Satyanarayana on 2014-10-21

Pani version 0.1 has been released.

Pani is a glue tool that provides a web interface atop hg-ssh. Through the web interface, you can add, modify and remove packages and assign access to users.

The documentation is also available.

How To Change Hostname In CentOS 7

written by Sudheer Satyanarayana on 2014-10-07

CentOS 7 comes with the hostnamectl utility to read and write hostname.

To view the hostname simply run the command:

hostname

[root@c7p1 ~]# hostnamectl
Static hostname: localhost.localdomain
Icon name: computer
Chassis: n/a
Machine ID: cda43e8062fb4d5881491f41e06a0c0d
Boot ID: 7cb835d3dd64468392e3399d771051ac
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-123.el7.x86_64
Architecture: x86_64

To set a hostname:

hostnamectl set-hostname mynewhostname

Example:

hostnamectl set-hostname c7p1.v.lab.techchorus.net

How To Setup MySQL Replication

written by Sudheer Satyanarayana on 2013-11-05

In this tutorial, I will provide step by step process to setup MySQL replication. We will create one master and one slave. We will use two CentOS 6 servers - one for master and the other for slave. This following steps have been tested on two virtual machines.

Our master server will have IP address 192.168.122.10. Our slave server will have IP address 192.168.122.12.

You might want to run SELinux in permissive mode.

Perform these steps on the master:

Install MySQL server.

yum install mysql-server -y

Configure binary log and assign server ID to master. In /etc/my.cnf append the following to mysqld section:

log-bin=mysql-bin
server-id=1

Each server will have a unique ID. Our master will have ID 1 and slave 2.

Start the MySQL server.

/etc/init.d/mysqld start

Set up the initial MySQL server settings.

mysql_secure_installation

Create a MySQL user account and provide REPLICATION SLAVE access to it.

mysql> CREATE USER 'repl'@'192.168.122.12' IDENTIFIED BY 'secretpassword';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.122.12';

Be sure to replace 'secretpassword' with the actual password. Also, note that 192.168.122.12 is the IP address of the slave server. repl MySQL user will be able to access the master server only from the IP address 192.168.122.12.

Let us create a sample database, table and a row.

mysql>CREATE DATABASE sample;
mysql>USE sample;
mysql>CREATE TABLE mytable (mycol varchar(255));
mysql>INSERT INTO mytable VALUES ('first entry');

At this point, we will prepare the master server for replication.

First, we lock all the tables.

mysql>FLUSH TABLES WITH READ LOCK;

Then, we note down the binary log file and position.

mysql>  SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |     1377 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

The log file is mysql-bin.000003 and position is 1377. The values on your server may vary.

Don't exit the MySQL client. In a separate session/terminal run the following commands.

Stop MySQL server.

/etc/init.d/mysqld stop

Copy the files to the slave server.

rsync --recursive /var/lib/mysql root@192.168.122.12:/var/lib --exclude="mysql/mysql" --exclude='mysql-bin.*' --exclude='auto.cnf' -v

If you use other methods to copy the data, be sure to exclude mysql.bin, auto.cnf and mysql directory placed inside /var/lib/mysql.

auto.cnf was added in MySQL 5.6.

Start the MySQL server.

/etc/init.d/mysqld start

Perform these steps on the slave server.

Install MySQL server.

yum install mysql-server -y

Make sure mysql is the owner of the files.

chown -R mysql.mysql /var/lib/mysql/

Edit /etc/my.cnf and append the following line in mysqld section.

server-id=2

Start the MySQL server.

/etc/init.d/mysqld start

Perform the initial settings.

mysql_secure_installation

Inform the slave how to access the master server.

mysql> CHANGE MASTER TO
        MASTER_HOST='192.168.122.10',
        MASTER_USER='repl',
         MASTER_PASSWORD='secretpassword',
         MASTER_LOG_FILE='mysql-bin.000003',
         MASTER_LOG_POS=1377;

Remember 1377 is the position and mysql-bin.000003 is the log file name after we locked the tables on master and copied the files.

Start the slave.

mysql> START SLAVE;

You can check the slave status using:

mysql> SHOW SLAVE STATUS\G;

Here's a sample output:

mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.122.10
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 214
               Relay_Log_File: mysqld-relay-bin.000003
                Relay_Log_Pos: 359
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 214
              Relay_Log_Space: 660
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
1 row in set (0.00 sec)

ERROR: 
No query specified

The key fields are Slave_IO_State, Slave_IO_Running and Slave_SQL_Running.

Let's see if our sample database has been copied.

mysql> USE sample;
mysql> SELECT * FROM mytable;

On the master run a few SQL statements.

mysql> USE sample;
mysq;> INSERT INTO mytable VALUES ('second entry');

On the slave, verify whether replication is working.

mysql> USE sample;
mysql> SELECT * FROM mytable;

Reference: MySQL reference manual

How To Setup php-fpm And Nginx On CentOS 6

written by Sudheer Satyanarayana on 2013-05-19

FPM, FastCGI Process Manager is a PHP FastCGI implementation. Using php-fpm you can have a website running as its own user instead of a common user like Apache or www-data. In this post, we will go through the process of installing and configuring php-fpm with Nginx on CentOS 6.

php-fpm package is available in the official CentOS repository. There is no need to enable third party repositories in order to use php-fpm.

nginx package is available in Fedora EPEL repository.

Enable Fedora EPEL.

rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

Install nginx and php-fpm packages.

yum install nginx php-fpm

Create a user for our website.

useradd webuser1

As user webuser1, create the directory where we will have our PHP scripts.

mkdir  /home/webuser1/www/public -p

Also create the log directory.

mkdir /home/webuser1/logs

Let web server execute files in our home directory.

chmod o+x /home/webuser1/

Create the file /home/webuser1/www/public/index.php and write some sample PHP code in it.

<?php
phpinfo();
?>

Configure php-fpm. Craete the file /etc/php-fpm.d/webuser1.conf and add the below contents.

[webuser1]
listen = 127.0.0.1:9001
listen.allowed_clients = 127.0.0.1
user = webuser1
group = webuser1

pm = dynamic
pm.max_children = 15
pm.start_servers = 3
pm.min_spare_servers = 1
pm.max_spare_servers = 5
pm.max_requests = 2000

request_slowlog_timeout = 5
slowlog = /home/webuser1/logs/webuser1.slow.log

php_admin_value[error_log] = /home/webuser1/logs/webuser1.error.log
php_admin_flag[log_errors] = on

The FastCGI server runs on port 9001 and the IP address 127.0.0.1. The process user and group should be webuser1. We also specify where to send the logs. Start php-fpm daemon.

/etc/init.d/php-fpm start

Configure Nginx. Within /etc/nginx/nginx.conf in the http block, add:

server_names_hash_bucket_size 64; Create the file, /etc/nginx/conf.d/webuser1.conf and append the following contents.

server {
    listen       80;
    server_name yourwebsite.example.com;

    root   /home/webuser1/www/public;
    index  index.html index.htm index.php;

    location ~ \.php$ {
      fastcgi_pass   127.0.0.1:9001;
      fastcgi_index  index.php;
      fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
      include        fastcgi_params;
    }
}

Start Nginx.

/etc/init.d/nginx start

That is all you have to do to setup php-fpm and Nginx on CentOS 6.

How To Comment Several Lines Quickly Using VIM

written by Sudheer Satyanarayana on 2012-12-20

If you have to insert comment on several lines do you do manually insert the comment character in every line? Stop. Vim is a really good editor and has a nice feature to accomplish this quickly. Here are the steps:

  1. Enter visual blocking mode by pressing CTRL V (CTRL key and the lowercase v). 1 .Make your selection using motion keys(jklm, etc).
  2. Press I(uppercase I) to enter block insert mode.
  3. Press #, the comment character.
  4. Press Esc key. The comment character # will be inserted on each line the visual block selection.

Read more about visual blocking mode using the vim help topic visual-block. At the command line(:), type help visual-block.

How Many Seconds Are There Till End Of Month?

written by Sudheer Satyanarayana on 2012-09-17

(datetime.datetime(datetime.datetime.today().year, datetime.datetime.today().month, calendar.monthrange(datetime.datetime.today().year, datetime.datetime.today().month)[1]) - datetime.datetime.today()).total_seconds()

There's a log going on in that one liner. Let's break it down.

The two key Python modules we need to calculate the number of seconds till the end of year are datetime and calendar.

calendar.monthrange(year, month) returns a tuple. The tuple's second element is the number of days in the month.

We create two date objects: date object 1: today date object 2: the last day of the month

We subtract object 1 from object 2. Finally, we call .total_seconds() on the resultant object.

>>> import datetime
>>> import calendar
>>> (datetime.datetime(datetime.datetime.today().year, datetime.datetime.today().month, calendar.monthrange(datetime.datetime.today().year, datetime.datetime.today().month)[1]) - datetime.datetime.today()).total_seconds()
1290914.259939
>>>

Mercurial - How To View A File Exactly Like It Appeared On A Particular Date

written by Sudheer Satyanarayana on 2012-03-19

Here's a quick tip for Mercurial users.

Travel back in time and see how the file appeared. :)

hg cat --rev "date('2011-05-03')" controllers/crons.py

Let's break it down.

hg cat is the command we use to print the given revision of file.

hg cat --rev 10885:ae28ee103fed controller/crons.py

would print the file for the revision 0885:ae28ee103fed.

Mercurial supports a functional language for selecting a set of revisions. To know more about it try:

hg help revsets

In our solution:

hg cat --rev "date('2011-05-03')" controllers/crons.py

"date('2011-05-03')" is the revset we used in cat. Notice that the revset has to be quoted. The date spec also requires quoting. Hence, a pair of single and double quotes.

To see what kind of date formats Mercurial supports run:

hg help dates

Writing A Python Script To Send Files To Amazon S3

written by Sudheer Satyanarayana on 2011-09-25

Amazon Simple Storage Service or Amazon S3 is a storage service with a web API. I use Amazon S3 to store backups of my blog and other sites. I made a simple python script to handle file uploads to S3.

In order to use Amazon S3, first create a bucket using your Amazon AWS account. As the name suggests, bucket is a container. You can create buckets using the AWS management console.

The script we're going to write will take two input parameters

Path to file, local Target S3 path Amazon S3 buckets don't support hierarchical directories. To simulate such a file system, you can use '/' in the target file name.

To use AWS from Python, boto is the de facto recommended library. You can install boto from your distribution package management system or download from code.google.com repository.

Import the libraries:

#!/usr/bin/env python

import os
import sys

from boto.s3.connection import S3Connection
from boto.s3.key import Key
Read the command line arguments:

local_file_path = sys.argv[1]
s3_path = sys.argv[2]

Using AWS Identity and Access Management (IAM) service, create an account which you can use from scripts. Make a note of the key and secret of the newly created account.

I have named my bucket 'j_bucket'.

Initialize the connection:

conn = S3Connection('your account key', 'your account secret')
pb = conn.get_bucket('j_backups')

Now, we're ready to create an S3 key. Once the key object is created, wet set the contents of the key and also the name of the key.

k = Key(pb)
file_name_to_use_in_s3 = "%s/%s"%(s3_path, os.path.basename(local_file_path))
k.name = file_name_to_use_in_s3
k.set_contents_from_filename(local_file_path)
sys.exit(0)

Save the file as send-to-s3.py and set execute permissions. We can now use the script like:

./send-to-s3.py path/to/my/local/file "mystore/mybackups"

In this example. the file "path/to/my/local/file" will be transferred to S3 bucket with the name "mystore/mybackups".

The script is also available on github.