Wednesday, October 23, 2019

Pattern to solve circular dependencies in node,

This is an useful pattern to avoid circular dependencies while requiring other files in node.

Circular dependencies manifest when a require returns an empty object: "the circular dependency means that other code receives an incomplete module object"

The solution is to 'augment' the exports instead of replacing it. 
So, if another module got a reference to the exported members they are eventually completed.

//requires at the beginning, as usual
//.. 


const PublicMethods = {
 method1: () => {},
 method2: (x) => {...},
 ...
]; 

// -- private & other methods
... 
...

//augment the exports at the end of the file:
Object.assign(module.exports, PublicMethods);



Wednesday, August 23, 2017

Get Response Time with Curl - curltime

Save this script in your path  (echo $PATH) as curltime:

#!/bin/bash

/usr/bin/curl -o /dev/null \
-s -w "    time_namelookup:  %{time_namelookup}\n       time_connect:  %{time_connect}\n    time_appconnect:  %{time_appconnect}\n   time_pretransfer:  %{time_pretransfer}\n      time_redirect:  %{time_redirect}\n time_starttransfer:  %{time_starttransfer}\n                    ----------\n         time_total:  %{time_total}\n" \
$1


Make it executable

chmod 0755 /usr/local/bin/curltime


Now you can use it to check the response time of an url. Ex:

curltime https://marca.com

Source: based on https://viewsby.wordpress.com/2013/01/07/get-response-time-with-curl/

Wednesday, June 14, 2017

Merge 2 commits when there are commits in between

Super handy trick based on based on https://stackoverflow.com/questions/30704254/merge-two-commits-where-commits-are-between

Lets say we have 2 commit we want to merge

f68ffb5 commit 6
...
d294fac commit 1


This is important: you have to give reference to a commit before the first one involved (in this case, the one that you want to squash to). Here we make the "before" reference with ^.

# rebase to the commit **before** commit 1
git rebase -i d294fac^

You invoked an interactive rebase. An editor window opens. Rearrange commits as desired (read the notes in the editor that opens)

In this list the commits go in reverse order (not as in git log): from the earliest to the latest.

Rearrange lines in the following way:

pick d294fac     //--- commit 1
squash f68ffb5   //--- commit 6
pick       //--- commit 2
pick       //--- ommit 3
pick       //--- commit 4
pick       //--- commit 5


or (leave the squashed commits in last place)
pick d294fac     //--- commit 1
squash f68ffb5  
//--- commit 6
pick      
//--- commit 2
pick      
//--- ommit 3
pick      
//--- commit 4
pick      
//--- commit 5

Tuesday, September 6, 2016

Back In Time: Backups for your personal computer


'Back in Time' ( http://backintime.le-web.org/ ) is a linux program to make regular backups. I recommend it.

Why?

  • simple. Linux only.
  • it uses incremental backups and hardlinks, saving time and space between 'snapshots'
  • 'snapshots' are saved as folders. Each snapshot is seen as a 'copy' of the system at a given time, but you still can get the 3-weeks ago version of a file, just by moving inside the file-tree of the snapshot. This is key: you can plug your backup drive to another computer and access the snapshots from the file explorer. No need to install anything to read the backup
  • autoremove old backups based on age or free space
  • backups are made to a drive or a remove machine (ssh). No cloud storage option (S3, box, etc)
  • handles backups of several machines with no extra configuration. Snapshots of different machines are stored in different folders
  • Just works


How I use it

(for all my computers) I run Back in time backups on demand (not scheduled) and unencrypted. Both options are available if needed.
Backups are stored in a ext4 external drive (ext4 is linux native but still read-accessible from OSX and Windows)


Install

This works for ubuntu. For others, go to the original http://backintime.le-web.org/

sudo add-apt-repository ppa:bit-team/stable
sudo apt-get update
sudo apt-get install backintime-gnome
Note: latest versions are only qt-based. You could install the `backintime-qt4` package instead `backintime-gnome`

Configure

Connect the external drive for the backups, and launch Back in Time. The first time you need to configure how to make backups for the computer (accessible from settings / preferences as well).

 

In the settings, you need to set where and when to save snapshots. For example I choose

[General] tab
  • Profile: Main profile
  • Mode: local (or local encrypted)
  • Where to save snapshots / destination: your drive , partition or subfolder.
  • Schedule disabled. I will save a new snapshot on demand
[Include] , [Exclude] tab
I usually include the home folder, or just the Documents, Pictures and .ssh folder. I exclude the Music and Videos folder.

[Autoremove]
defaults are good for me

[Options] 
  • Check Use checksum to detect changes
  • Check Full rsync mode (or not)
  • Check Backup replaced files on restore
  • Uncheck 'continue on errors'


[Expert options]

  • Uncheck any option related to cron
  • Check ‘Run ionice’ when taking a manual snapshot
  • you may check 'Preserve ACL' ( as src and dst are Ext4, otherwise uncheck ). I finally uncheck it since gave me errors for some of my files


-


Save configuration > OK

New backup

You can make a new backup clicking on the 'disk' icon on the main toolbar. The first backup might take some minutes. Newer snapshots execute faster.





In case you need to back up files with special permission, you might need to run your backintime with sudo. The profile id is in the Settings > General , in the Advanced section

sudo -i backintime-qt4 --config ~/.config/backintime/config --profile-id 1

Uninstall

sudo ppa-purge ppa:bit-team/stable
sudo apt-get remove backintime-*

Saturday, September 3, 2016

Nautilus: Add touch action in context menu

This is a modification I make to nautilus in every computer I own.

Just make a 'touch' option available when you select a file or folder. This tutorial can be modified to include other commands as well. I have used it for Ubuntu 12.04, 14.04 and 16.04.



First, install nautilus actions

sudo apt-get install nautilus-actions

and launch it.

nautilus-actions

(1) Create a new item
  • Create the item using the '+' icon and name the action (Ex: 'Touch'). Use a short name, since it is used in teh context menu
  • Edit Action and Command tabs accordingliy. Ex:
    • Path: /usr/bin/touch
    • Parameters: %F (see Legend button to get more options)
    • Working directory: %d
  • Save (icon save)




(2) Right click on the new action that appeared in the Item list area
  • go to preferences
  • Ensure the 'Nautilus menu layout' > 'Create a root...' is disabled

Restart Nautilus
pkill nautilus


Well done!

Sunday, July 19, 2015

How to determine the time zone of an IP in Ruby

In ruby / Rails, you may need to get the timezone of an ip address.

One of the best options is the Maxmind.com GeoIP . The solution provided here applies to geolocate an IP address to get the timezone, country, city etc

Local or Remote

For better results I recommend to use their web service to geolocate a city : http://dev.maxmind.com/geoip/geoip2/web-services .
The service is not free but you can pay 20$ for 50K resolutions. Fair enough.
I write a new post on how to query the web service.

Another option is to resolve the geolocation locally. Maxmind provides a free database that is updated every month. As a free product, it is less accurate than the web service but gives good results. http://dev.maxmind.com/geoip/legacy/geolite/

Local set up

We need:
- download the database
- include the `geoip` gem, that will read the database
- our code to query the geoip gem
- link back to Maxmind

Download database

Read http://dev.maxmind.com/geoip/legacy/install/city/ for instructions. It boils down to:

cd /tmp
wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
mv GeoLiteCity.dat /usr/local/share/GeoIP/

I recommend you to make a bash script with these commands and run a cron once a month

Required gem


To read the legacy GeoIP database I recommend the pure ruby geoip gem. Just include in your Gemfile
 gem 'geoip'

or
 gem install geoip

Boilerplate

The interface of GeoiP gem is really simple however, as we are using a database with less than 100% accuracy, we should account for cases where timezone is not available.
When a ip resolves to a location without timezone, the best trick I found was to try with 'enclosing' networks (bigger supernets) until a result has timezone. That is: first try a perfect match, then try for the network with the last bit of the address masked, then mask 2 bits ...  https://en.wikipedia.org/wiki/Subnetwork#Subnet_and_host_counts


class Ip2Geo

  DB_PATH = '/usr/local/share/GeoIP/GeoLiteCity.dat'

  def timezone(ipv4)
    if ipv4.present?
      addr = IPAddr.new(ipv4.to_s.strip)
      32.downto(16).map do |mask| #if an address fails, test with enclosing network X.X.X.X , X.X.X.0 , X.X.0.0 ...
        network = addr.mask(mask).to_i
        c = db.city(network)
        if c && c.timezone
          return c.timezone
        end
      end
    end
    nil
  end
#a similar pattern can be re-used
  def country_code(ipv4)
    if ipv4.present?
      candidate = ipv4.to_s.strip
      addr = IPAddr.new(ipv4.to_s.strip)
      32.downto(16).map do |mask|
        network = addr.mask(mask).to_i
        c = db.city(network)
        if c && c.country_code2
          return c.country_code2
        end
      end
    end
    nil
  end

  def location(ipv4)
    if ipv4.present?
      candidate = ipv4.to_s.strip
      addr = IPAddr.new(ipv4.to_s.strip)
      32.downto(16).map do |mask|
        network = addr.mask(mask).to_i
        c = db.city(network)
        return c if c
      end
    end
    nil
  end


  def db
    @db ||= GeoIP.new(DB_PATH)
  end

end

To resolve the ip

locator = Ip2Geo.new
locator.timezone('193.110.128.199')

Attribution

Remember that the use of the free database requires an attribution: The attribution requirement may be met by including the following in all advertising and documentation mentioning features of or use of this database 
This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com



Friday, June 12, 2015

Canon lide 220 in Ubuntu 14.04

Last week I bought a Canon lide 220 scanner. You get a decent device for the price.

(since I had to read several posts) Here are in a single page all the steps I needed to make it work in Ubuntu 14.04 (via xsane).

connect the scanner

ensure it is recognized

    lsusb

in teh output, search for the Canon device

...
Bus 003 Device 003: ID 04a9:190f Canon, Inc.
...

ensure your user has access to the bus (otherwise  you'll have to launch everytime  xsane as root)

    sudo chmod u+w /dev/bus/usb//

in my case

 sudo chmod u+w /dev/bus/usb/003/003

Then, add this ppa to install latest version of xsane

sudo add-apt-repository ppa:rolfbensch/sane-git

and install xsane

    sudo apt-get update && sudo apt-get install gocr libsane-extras xsane-common xsane

if you have problems, install a couple of additional packets with

    sudo apt-get update && sudo apt-get install gocr libusb-dev libsane-dev libsane-extras xsane-common xsane

now you can run

  xsane


 and the scanner is working!