Browsing without ads on mobile browsers

This post used to recommend a now-defunct Android app called “Ad Block” that turned your phone into its own proxy server. The app is gone, the Play Store link is dead, and the proxy-based approach has been superseded several times over. Mobile ad blocking is genuinely easier now than it was a decade ago — here’s what actually works today.

The four approaches, and which one fits you

Every working option boils down to one of these four:

  1. A browser that blocks ads natively. Easiest. Install the browser, you’re done.
  2. A regular browser plus a content-blocker extension. Familiar if you do this on desktop.
  3. A DNS-based blocker that works system-wide — every app, not just browsers.
  4. Network-level blocking (Pi-hole on your home router). Best in your living room, irrelevant on cellular.

Most people end up with a combination — a content-blocking browser for everyday use, plus a DNS blocker for everything else.

On Android

Browsers with built-in blocking. The simplest path:

  • Brave — Chromium-based, blocks ads and trackers by default, no setup. The most “it just works” option for someone who’s never thought about this before.
  • Vivaldi — also Chromium-based, blocking is on by default with a more granular control panel.
  • Cromite (formerly Bromite) — a privacy-hardened Chromium fork with built-in adblocking. Niche, but well-regarded by people who care about this stuff.
  • Mull — a Firefox-based browser with privacy patches and uBlock Origin pre-configured. F-Droid only, not Play Store.

Firefox for Android with extensions. Firefox is the only major mobile browser on Android that supports a real desktop-style extension system, and that’s a big deal. You can install:

  • uBlock Origin — the gold-standard content blocker. Free, open-source, no “acceptable ads” program. This is the one I’d recommend.
  • AdBlock Plus — works fine but ships with an “acceptable ads” allowlist enabled by default; you can disable it in settings if you want. The original AdBlock that this post used to recommend by name.
  • Ghostery — focused more on tracker blocking than ad blocking, with a nicer UI for seeing what each page is trying to load.

Open Firefox for Android, tap the menu, choose “Add-ons,” and install the one you want.

System-wide DNS blocking. The trick that works for every app on your phone — not just browsers — is to point your DNS at a service that returns NXDOMAIN for known ad/tracker hosts. No root required, no proxy, no app permissions to worry about:

  • NextDNS — a configurable DNS service with a generous free tier. You enable it once via Android’s Private DNS setting (Settings → Network & internet → Private DNS) and pick which blocklists to apply.
  • AdGuard DNS — similar idea, also free for personal use.
  • AdGuard for Android (the standalone app, not the DNS service) does this plus content filtering. Note: not in Play Store because Google’s policies forbid system-wide ad blockers; install via the AdGuard website.

DNS-based blocking is the closest spiritual successor to the proxy trick from this post’s original incarnation — same idea (intercept network requests before they fetch ads), better implementation (kernel-level, supports HTTPS, no app to babysit).

On iOS

iOS is more constrained, because Apple’s WebKit policy means every browser on iOS is just a Safari skin with branding. Firefox on iOS doesn’t run Gecko; Chrome doesn’t run Blink. Real desktop-style extensions don’t exist there. So the techniques are different:

  • Safari content blockers. Apple has a first-party API for this. Install 1Blocker, AdGuard for Safari, or Wipr from the App Store, then enable it in Settings → Safari → Extensions. These work in Safari only.
  • Brave on iOS — still WebKit under the hood, but Brave’s built-in shields work because they’re applied via Apple’s content-blocker API, same plumbing as the standalone blockers.
  • System-wide DNS blocking works exactly like on Android: Settings → General → VPN & Device Management → DNS, or install the NextDNS/AdGuard configuration profile. Same NXDOMAIN trick, blocks across all apps.

Firefox for iOS does not support uBlock Origin or any other extension in the desktop sense. If you came here looking for that specifically, the answer is “not possible on iOS — use a Safari content blocker plus a DNS blocker.”

What I’d actually do

If I were setting up a phone from scratch and wanted no ads with minimum fuss:

  • Android: Install Brave for casual browsing, Firefox + uBlock Origin for anything where you want fine control, and configure NextDNS or AdGuard DNS as Private DNS for system-wide coverage of in-app ads.
  • iOS: Install AdGuard for Safari (or Wipr if you want something simpler), and add the NextDNS configuration profile.

The setup is reversible and free, and you’ll save a meaningful chunk of mobile data along the way. 🎉

Two notes worth knowing. Some sites detect ad blockers and refuse to load — that’s between you and the publisher, but most blockers have a one-tap “disable on this site” button for the rare cases where you decide it’s worth it. And remember that if you’re paying for a service (a subscription, a one-time purchase), you’re often the customer and not the product; the case for blocking ads on those sites is weaker, and many will let you disable ads in settings if you ask.

Posted in Android | Comments Off on Browsing without ads on mobile browsers

Benchmark How Long a Program Runs In Linux Using Bash

The following bash code might come in handy if you want to benchmark how long a program runs. The example assumes you want to pass two parameters along to the program. A timestamp is captured at the start and end of execution, and the difference (the processing time) is printed in seconds.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
##################################################
# Benchmark the processing time when a program
# executes with two required parameters: parameter1 parameter2
##################################################

if [[ $1 = "" || $2 = "" ]]; then
        echo "Usage: `basename $0` parameter1 parameter2"
else
        _start_time=`date +%s`
        _parameter1=$1
        _parameter2=$2
        ### YOUR COMMAND HERE WITH parameter1 AND parameter2 ###
        _end_time=`date +%s`
        _processing_time=$((_end_time-_start_time))
        echo "Source File: $_parameter1"
        echo "Destination File: $_parameter2"
        echo "Start time: $_start_time"
        echo "End time: $_end_time"
        echo "Processing time is: $_processing_time"
fi

A few useful additions.

One thing to know about the script above: the ### YOUR COMMAND HERE ### line is just a comment — bash doesn’t run anything. If you copy-paste and try it, you’ll get Processing time is: 0 because the timer fires at _start_time, immediately advances to _end_time, and there’s nothing in between. Replace that comment with the actual command you want to measure, e.g.:

1
rsync -a "$_parameter1" "$_parameter2"

The simpler answer: time. If “how long did this take?” is the only question you’re asking, bash already has a builtin for it:

1
2
3
4
time ./myprogram param1 param2
# real    0m1.234s
# user    0m0.045s
# sys     0m0.012s

The three numbers are: wall-clock time (real), CPU time spent in user-mode code (user), and CPU time spent in kernel calls (sys). When user + sys is much less than real, your program was waiting on something (disk, network, sleep). When they’re roughly equal, it was CPU-bound.

The time keyword also wraps a whole pipeline or compound command:

1
time { ./step1 && ./step2 | tee out.log; }

The richer answer: /usr/bin/time. The standalone GNU time binary (different program, same name — note the explicit path or you’ll get the bash builtin) reports a lot more:

1
2
3
4
5
6
7
8
/usr/bin/time -v ./myprogram param1 param2
# Command being timed: "./myprogram"
# Maximum resident set size (kbytes): 12480
# Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.23
# Percent of CPU this job got: 87%
# Major (requiring I/O) page faults: 0
# Minor (reclaiming a frame) page faults: 1532
# ...

That’s the one to reach for when you care about memory usage, page faults, or context switches alongside timing. Some distros don’t ship it by default — apt install time or dnf install time if it’s missing.

Sub-second timing without date +%s. The original script’s resolution is one second, which is too coarse for anything fast. A few ways to get finer numbers:

1
2
3
4
5
6
7
8
9
10
11
# Nanosecond resolution via date (still spawns a subprocess each call)
_start=$(date +%s%N)
# ... work ...
_end=$(date +%s%N)
echo "$(( (_end - _start) / 1000000 )) ms"

# Bash 5+ has $EPOCHREALTIME — sub-second, no subprocess at all
_start=$EPOCHREALTIME
# ... work ...
_end=$EPOCHREALTIME
awk -v s="$_start" -v e="$_end" 'BEGIN { printf "%.3f s\n", e - s }'

$EPOCHREALTIME is a string like 1715000123.456789 with microsecond resolution. It’s free — no fork, no exec — so it’s safe to call inside a hot loop. The catch: bash arithmetic is integer-only, so you need awk or bc to do the floating-point subtraction.

When you want statistical confidence: hyperfine. If the question is “is my new version actually faster?” — you want averages over many runs, with warmup, and ideally a confidence interval. hyperfine is the modern tool for this:

1
2
3
4
5
6
hyperfine --warmup 3 --runs 20 \
    './build_old.sh input.txt' \
    './build_new.sh input.txt'
# Summary
#   './build_new.sh input.txt' ran
#     1.42 ± 0.03 times faster than './build_old.sh input.txt'

It runs each command repeatedly, discards the warmup runs (which are usually slower because of cold caches), reports mean ± standard deviation, and gives you a relative-speedup figure. If you’re benchmarking anything where one-off variance matters — and that’s most things — this beats running time three times and squinting at the numbers.

Two gotchas worth knowing.

  • System clock changes break date +%s. If NTP slews the clock backwards mid-run, your _processing_time can be negative or inflated. $EPOCHREALTIME has the same problem (both read CLOCK_REALTIME). For benchmarking, the correct clock is CLOCK_MONOTONIC, which never goes backwards — but bash doesn’t expose it directly. Use time or hyperfine for anything that needs to survive a clock change.
  • Disk caches make repeated runs misleadingly fast. The first run of a program reads cold data from disk; the second run hits the page cache and looks 10x faster. Either drop caches between runs (echo 3 | sudo tee /proc/sys/vm/drop_caches on Linux) or — easier — let hyperfine handle the warmup phase for you.
Posted in Linux, Operating System, Ubuntu | Comments Off on Benchmark How Long a Program Runs In Linux Using Bash

Auto Login Using SSH Public and Private Keys

2026 update: This post originally used ssh-keygen -t rsa. The current recommendation (e.g. GitHub’s SSH key guide) is Ed25519 — it produces shorter keys, is faster, and is considered more secure. Use RSA (4096-bit) only as a fallback for systems that don’t support Ed25519.

The -C “your_email@example.com” flag is just a comment/label embedded in the public key — it has no effect on the cryptography. It’s helpful for identifying which key is which when you have several. You can put any string there (or omit -C entirely). 🔐


Assume that your main server (the one you use the most) is ServerA. And from ServerA, you want to automatically login to ServerB. For illustration purpose, ServerB can be a repo server and you don’t want to keep being asked for password everytime you want to commit files.

1. At ServerA issue:

1
ssh-keygen -t ed25519 -C "your_email@example.com"

This will create a public + private key for ServerA.

2. Enter (empty) for passphrase

1
2
Your identification has been saved in /home/ronald/.ssh/id_ed25519.
Your public key has been saved in /home/ronald/.ssh/id_ed25519.pub.

3. Copy over the newly created public key from ServerA to ServerB:

1
scp .ssh/id_ed25519.pub ronald@ServerB:~/id_ed25519.pub.ServerA

Note that once the file arrives at ServerB, it named as id_ed25519.pub.ServerA (not id_ed25519.pub), and it will be stored at ronald’s home directory at ServerB.

4. Ssh to ServerB, and issue this command:

1
cat id_ed25519.pub.ServerA >> .ssh/authorized_keys

ServerA public key will be merged/appended to ServerB authorized_keys file.

This way everytime you want to access ServerB from ServerA, you won’t be asked for a password. 🎉

Posted in Linux, Operating System, Ubuntu | Comments Off on Auto Login Using SSH Public and Private Keys

Linux symlinks: creating, deleting, and the gotchas worth knowing

The basic command for creating a symbolic link (a “symlink” or “soft link”) to a folder or file is ln -s:

1
2
3
4
5
6
7
8
ln -s /home/ronald/somefolder /home/ronald/newfolder

# or if your current directory is already /home/ronald:
cd /home/ronald
ln -s somefolder newfolder

# general form:
ln -s existingSourceFolder newLinkedFolder

The first argument is the target (what the link points at), the second is the link name (what gets created). I get this order backwards every time — the mnemonic that finally stuck is “ln -s is like cp: source first, destination second.”

To remove all symlinks in the current directory (and only symlinks — leaving regular files and directories untouched):

1
find . -maxdepth 1 -type l -exec rm -f {} \;

-type l is the filter that matches symlinks specifically. -maxdepth 1 keeps the search from descending into subdirectories, so you only kill the symlinks at the top level.


A few useful additions: symlinks have sharp edges.

Symlinks look simple — “a file that points to another file” — but they have a handful of behaviors that catch people out. The ones below are the ones I’ve actually been bitten by.

Symlinks vs. hard links. The -s in ln -s is the difference. Without it, you get a hard link: a second directory entry pointing to the same inode. Hard links don’t break if you move or rename the original (because both names refer to the same data). Symlinks store a path and break if the target moves. Hard links can’t span filesystems and can’t point to directories (the kernel forbids it to prevent loops); symlinks can do both.

Inspecting a symlink. A few different tools answer different questions:

1
2
3
4
5
ls -l newfolder              # shows: newfolder -> /home/ronald/somefolder
readlink newfolder           # prints just the target: /home/ronald/somefolder
readlink -f newfolder        # follows all symlinks, prints absolute target
realpath newfolder           # same idea as readlink -f, slightly different edge cases
stat newfolder               # full metadata; "File: newfolder -> ..."

readlink -f is the one I reach for most — it tells you where a symlink ultimately resolves, even through chains of symlinks-pointing-to-symlinks.

Relative vs. absolute targets. The path you pass as the target is stored verbatim. If you write a relative target, it’s resolved relative to the directory the link lives in, not the directory you ran the command from. This trips people up:

1
2
3
4
5
6
cd /tmp
ln -s ../etc/hosts mylink         # mylink points to ../etc/hosts
                                  # which from /tmp resolves to /etc/hosts ✓

mv mylink /var/log/               # now /var/log/mylink points to ../etc/hosts
                                  # which resolves to /var/etc/hosts ✗ broken

Rule of thumb: use absolute paths unless you specifically want the link to follow when both source and link move together (common pattern: shipping a relative symlink inside a tarball or git repo).

The rm -rf on a symlink-to-directory trap. This one is genuinely dangerous:

1
2
3
4
ln -s /important/data ./mydata
rm -rf mydata                # removes the symlink only — /important/data is safe
rm -rf mydata/               # WITH trailing slash: rm follows the link and
                             # recursively deletes /important/data

The trailing slash changes the command from “delete this symlink” to “delete what’s inside the directory the symlink points to.” If you’re in the habit of tab-completing paths, your shell often appends the slash for you. Be deliberate when removing symlinks to directories.

Updating an existing symlink. By default ln -s refuses to overwrite. The flags vary depending on what you’re replacing:

1
2
3
4
ln -sf newtarget mylink           # works for symlinks to files
ln -sfn newtarget mydirlink       # for symlinks to directories — without -n,
                                  # ln creates a NEW link INSIDE the existing
                                  # directory link instead of replacing it

Forgetting -n on a directory symlink is one of those bugs that’s invisible until you wonder why your link “didn’t take” — and meanwhile a stray newtarget entry is hiding in the linked directory.

Finding broken symlinks. Symlinks happily survive their targets being deleted. To find ones that no longer point anywhere valid:

1
2
find . -xtype l                          # broken symlinks under current dir
find / -xtype l 2>/dev/null              # the same, system-wide (slow)

-xtype l means “the symlink’s target is not a real file/directory we can stat” — i.e. the link is dangling. Useful as a periodic sanity check after you’ve moved or removed a directory that other things might have linked to.

Finding what links to a given target. The reverse question — “is anything pointing at this file?” — has no fast answer; you have to scan:

1
2
find / -lname "*somefolder*" 2>/dev/null    # by target pattern
find / -samefile /home/ronald/somefolder 2>/dev/null  # exact same inode

The first form matches the symlink’s stored target string; the second works for hard links (same inode). There’s no equivalent of “give me everything that resolves to this path,” because resolving every symlink on the system would be expensive — you’d be running readlink -f on every link in the search tree.

Posted in Linux, Operating System, Ubuntu | Comments Off on Linux symlinks: creating, deleting, and the gotchas worth knowing

A Linux primer: identifying your distro and other commands that work everywhere

Here are a few commands you can use to find out which Linux distribution you’re on — pick whichever your system has:

1
2
3
4
5
6
7
cat /etc/issue

cat /proc/version

dmesg | head -1

cat /etc/*-release

Of those, cat /etc/*-release is the most reliable on modern systems. The wildcard catches both /etc/os-release (the systemd-mandated standard, present on virtually all distros since around 2012) and any distro-specific files like /etc/redhat-release, /etc/lsb-release, or /etc/debian_version — so you don’t need to know in advance what the file is called.

If you only want a clean machine-readable answer and don’t care about the others, source /etc/os-release and read its variables directly:

1
2
. /etc/os-release
echo "$NAME $VERSION_ID"   # e.g. "Ubuntu 22.04"

A few useful additions: commands that work the same across distros.

One of the joys of Linux is that once you’ve learned the basics, the same commands work whether you’re on Ubuntu, Fedora, Arch, Alpine, or Amazon Linux. Here are some that show up in almost every troubleshooting session:

What kernel and architecture am I on?

1
2
3
uname -a              # full kernel info: kernel name, hostname, release, arch
uname -r              # just the kernel release (useful for matching kernel modules)
arch                  # CPU architecture: x86_64, aarch64, armv7l, etc.

How much memory and disk do I have?

1
2
3
free -h               # memory: human-readable units
df -h                 # disk usage by filesystem
du -sh /var/log       # size of a specific directory

What’s running and using resources?

1
2
3
ps aux                # all processes, BSD-style output
top                   # interactive process viewer (q to quit)
htop                  # nicer interactive viewer (often needs install)

Who am I, where am I, what’s the time?

1
2
3
4
5
6
whoami                # current user
id                    # user + group IDs
hostname              # machine name
pwd                   # current directory
date                  # current date and time, with timezone
uptime                # how long the system has been running, plus load average

Networking basics. The classic ifconfig and netstat are deprecated in favor of ip and ss, which ship with iproute2 and are present on every modern distro:

1
2
3
4
5
ip addr               # network interfaces and their IPs (replaces ifconfig)
ip route              # routing table (replaces route)
ss -tulpn             # listening TCP/UDP sockets with PIDs (replaces netstat)
ping -c 4 example.com # send 4 ICMP packets and stop
curl -I https://example.com  # fetch just response headers

Which desktop am I running? If you ssh into a graphical box and aren’t sure whether it’s GNOME, KDE Plasma, XFCE, Cinnamon, or something else, two environment variables will tell you:

1
2
echo $XDG_CURRENT_DESKTOP    # GNOME, KDE, XFCE, MATE, X-Cinnamon, etc.
echo $DESKTOP_SESSION        # the session name (often more specific)

Both are set by the display manager when you log in graphically; they’re empty if you’re on a headless box or in a plain ssh shell that didn’t inherit them. If they come back empty but you know there’s a desktop running, this works too:

1
ps -e | grep -Eo 'gnome-shell|plasmashell|xfce4-session|cinnamon|mate-session' | head -1

X11 or Wayland? Once you’ve got a desktop, the next question is which display server it’s drawing through. The simplest check is the session-type variable, set by systemd’s logind:

1
echo $XDG_SESSION_TYPE       # "x11" or "wayland"

If that’s empty (again, common over plain ssh), use loginctl to ask the session manager directly:

1
2
loginctl show-session $(loginctl | awk 'NR==2 {print $1}') -p Type
# Type=wayland

And if you want to see whether the Wayland or X11 socket actually exists on the system:

1
2
ls /run/user/$(id -u)/wayland-*    # Wayland socket(s) for your user
ls /tmp/.X11-unix/                  # X11 sockets (one per :display)

Why this matters: some tools behave differently or don’t work at all under Wayland (screenshot utilities, screen sharing, global hotkey daemons, automation tools like xdotool). When something graphical “just doesn’t work” on a modern Linux desktop, “are you on Wayland?” is often the first question to ask.

Looking for files and text.

1
2
3
4
find / -name "*.conf" 2>/dev/null      # find files by name
grep -rni "error" /var/log              # recursive case-insensitive search
locate sshd_config                      # very fast — uses an index, may need updatedb
which python3                           # path to a command in $PATH

Permissions and ownership.

1
2
3
4
ls -la                                  # detailed listing with permissions
stat /etc/passwd                        # all metadata for a file
chmod 644 file.txt                      # rw for owner, r for group/others
chown user:group file.txt               # change owner and group

Service management. Systemd is the init system on virtually every mainstream distro now (Debian, Ubuntu, RHEL/Fedora, SUSE, Arch). The same systemctl commands work everywhere:

1
2
3
4
5
6
systemctl status nginx                  # is it running?
systemctl start nginx
systemctl stop nginx
systemctl enable nginx                  # auto-start at boot
systemctl restart nginx
journalctl -u nginx -f                  # tail the service's logs

Alpine and a few minimalist distros use OpenRC instead (rc-service, rc-update) — worth knowing when you ssh into a small container.

Where the distros do diverge: package management. This is the one place you have to know which family you’re on:

1
2
3
4
5
Debian / Ubuntu      apt install <pkg>     apt update / apt upgrade
RHEL / Fedora / CentOS dnf install <pkg>   dnf update          (yum on older releases)
openSUSE             zypper install <pkg>  zypper refresh / zypper update
Arch                 pacman -S <pkg>       pacman -Syu
Alpine               apk add <pkg>         apk update / apk upgrade

If a script needs to work across families, the cleanest pattern is to detect $ID from /etc/os-release and dispatch:

1
2
3
4
5
6
7
8
. /etc/os-release
case "$ID" in
    ubuntu|debian)        apt install -y curl ;;
    rhel|centos|fedora)   dnf install -y curl ;;
    arch|manjaro)         pacman -S --noconfirm curl ;;
    alpine)               apk add curl ;;
    *)                    echo "unsupported distro: $ID"; exit 1 ;;
esac

That’s the foundation. Once you have these committed to muscle memory, ssh-ing into an unfamiliar Linux box stops being intimidating — the same handful of commands answer the same handful of questions everywhere.

Posted in Linux, Operating System, Ubuntu | Comments Off on A Linux primer: identifying your distro and other commands that work everywhere

How to Set up an FTP Server in Ubuntu Linux

Login to your Linux shell menu as root

1
2
[root@locahost]# apt-get install vsftpd
[root@locahost]# vim /etc/vsftpd.conf

At VIM, 1st comment out anonymous_enable by adding a # sign at the beginning of the line
# anonymous_enable=YES
2nd remove comment at local enable by removing the # sign
local_enable=YES

1
[root@locahost]# /etc/init.d/vsftpd restart
Posted in Linux, Operating System, Ubuntu | Comments Off on How to Set up an FTP Server in Ubuntu Linux

Adding color to your tail

Tail is a very useful tool for monitoring an error stream. Sometimes the output from tail can have too much information, and its black-and-white monotone output can be hard to follow with the eyes.

The basic: a Linux terminal has the capability to colorize text. For example:

1
echo -e "Sample text nicely highlighted"

will produce a simple text saying, well:

Sample text nicely highlighted

But with some terminal color tagging such as:

1
echo -e "Sample \e[36mtext\e[0m nicely highlighted"

The \e above is identical to \033. I’d suggest using \033 because it’s safer in a programming language such as PHP. PHP will not recognize \e, but it will recognize \033, as you’ll see below.

1
echo -e "Sample \033[36mtext\033[0m nicely highlighted"

Sample text nicely highlighted

Some basic coloring tables can be seen at bashguru.com:

1
2
3
4
5
6
7
8
9
Color     Foreground  Background
Black     30          40
Red       31          41
Green     32          42
Yellow    33          43
Blue      34          44
Magenta   35          45
Cyan      36          46
White     37          47

With the help of perl, which most likely comes with all Linux distros, here’s a way to colorize your tail output. Let’s assume that every time you log something you will have a date-time prefixing your log. For example:

1
2
3
4
5
6
7
[22-Dec-2011 20:28:45] E_DATASOMETHING ......
Too much information .......
Too much information .......
[22-Dec-2011 20:28:46] E_FATAL Something
Too much information .......
Too much information .......
Too much information .......

Let’s create a script that can colorize the date portion. Create an executable Linux bash file:

1
2
3
touch logwatch.sh
chmod 755 logwatch.sh
vim logwatch.sh

Then copy and paste the following into your empty logwatch.sh:

1
2
3
#!/bin/bash
vNow=$(date +"%d-%b-%Y")
tail -f ~username/errorlogfile.txt | perl -pe "s/$vNow/\e[1;30;32m$&\e[0m/g"

Voilà!

[22-Dec-2011 20:28:45] E_DATASOMETHING ……
Too much information …….
Too much information …….
[22-Dec-2011 20:28:46] E_FATAL Something
Too much information …….
Too much information …….
Too much information …….

If you need something more complex — say you want to highlight several words in the file — you can use the scripting power of PHP. (I’m rusty with my perl.) Save the script below as colorize.php, and you can have the words blah, na, wa, and highlighted on the fly:

1
tail -f test.txt | php colorize.php blah na wa --
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
//stream_set_blocking(STDIN, FALSE);
$fp = fopen("php://stdin", "r");
// Failed to connect to STDIN? (shouldn't really happen)
if (!$fp) {
    echo "Cannot connect with standard input";
    exit();
}

array_shift($argv);
$replacements = array();
foreach ($argv as $arg) {
    $replacements[] = "\033[36m$arg\033[0m";
}

// Read each line as it arrives on STDIN
while ($line = fgets($fp)) {
    echo str_ireplace($argv, $replacements, $line);
}

// Close connection to STDIN
fclose($fp);
echo "done!";
?>

A few useful additions.

The simpler path: grep –color. If you only need to highlight a single pattern, you don’t need perl or PHP at all — grep can do it, and the –color=always flag forces color even through a pipe (where grep otherwise drops it because stdout isn’t a terminal):

1
tail -f errorlog.txt | grep --color=always -E "E_FATAL|E_ERROR|.*"

The trailing .* is the trick that makes this work as a highlighter rather than a filter — it matches every line, so nothing gets dropped, but the alternation patterns still get colored where they appear. The -E flag enables extended regex.

The line-buffering gotcha. When you chain tail -f through several filters, each program in the pipeline buffers its output by default. The result: nothing appears on screen for several seconds, then a wall of lines all at once — useless for live monitoring. Force line-buffering on each stage:

1
tail -f errorlog.txt | grep --line-buffered "ERROR" | sed -u 's/old/new/'

–line-buffered is the GNU grep flag; -u is the equivalent for sed; for awk, use fflush() after each print. If you don’t see live output through your pipeline, this is almost always why.

Purpose-built tools. If colorizing logs is something you do often, two tools save you from rolling your own:

  • ccze — pipe a log into it (tail -f /var/log/syslog | ccze -A) and it auto-colorizes by recognizing common log formats (syslog, Apache, Squid, etc.). The -A flag emits ANSI for piping; without it, ccze prefers its own curses-based UI.
  • multitail — like tail -f but with split panes for watching multiple files at once, plus per-pattern highlighting via a config file. Heavier but powerful when you’re staring at three log files at the same time.

Both are in the standard repos for Debian/Ubuntu/Fedora — apt install ccze multitail or equivalent.

Two reset bookkeeping notes. If your colored output starts “leaking” — i.e. text after a match keeps showing up colored — your reset escape (\e[0m) didn’t fire. Common causes: a trailing newline got stripped before the reset, or you forgot the reset entirely. Always pair \e[Xm with \e[0m. And if you ever end up in a terminal stuck in some weird color state, the command reset (or tput reset) puts everything back to defaults.

Posted in Linux, Operating System, Ubuntu | Comments Off on Adding color to your tail

JSON Jumpstart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
 * In JSON, curly brackets mark a new object ({ or })
 * Any variable inside the object — also known as the object's attribute — is
 * accessible using the dot syntax (object.attribute) or the bracket syntax
 * (object['attribute']).
 * Open your browser's DevTools console (F12 in any modern browser) to see
 * the output from console.log.
 */


// =========================
// JSON Object
// =========================
var var1 = {
    'var1_1':'value1_1',
    'var1_2':'value1_2'
};
console.log(var1);
// The line above will output> Object { var1_1="value1_1", var1_2="value1_2"}
console.log(var1.var1_1);
// The line above will output> value1_1
console.log(var1['var1_1']);
// The line above will output> value1_1

// =========================
// JSON Array
// =========================
// In JSON, square brackets mark an array ([ or ])
// Any array element is accessible by using a square bracket followed by an index (0,1,2,...)
var var2 = ['value2_1', 'value2_2'];
console.log(var2);
// The line above will output> ["value2_1", "value2_2"]
console.log(var2[0]);
// The line above will output> value2_1

var var3 = [{
        'var3_1':'value3_1',
        'var3_2':'value3_2'
    },{
        'var3_3':'value3_3',
        'var3_4':'value3_4'
    }];
console.log(var3);
// The line above will output> [Object { var3_1="value3_1", var3_2="value3_2"}, Object { var3_3="value3_3", var3_4="value3_4"}]
console.log(var3[0].var3_1);
// The line above will output> value3_1

A few useful additions.

JS objects vs. JSON — they look the same, but they aren’t. The examples above are JavaScript object literals, not strictly JSON. They render and behave the same way at the console, which is why the line between them blurs in tutorials, but there are real differences worth knowing:

  • JSON requires double-quoted string keys: “var1_1”, not ‘var1_1’.
  • JSON values can only be: string, number, boolean, null, object, or array. No undefined, no functions, no Date objects (they get serialized as strings).
  • JSON has no comments and no trailing commas.

If you write what looks like JSON in a .json file but use single quotes, your tool will reject it as invalid. The JS engine accepts both because it’s evaluating JavaScript syntax, not parsing JSON.

The actual JSON API. When you receive JSON from a network request and need to turn it into something you can manipulate — and vice versa — use the two builtins:

1
2
3
4
5
6
7
8
9
10
11
12
13
// JSON string -> JS object
var fromServer = '{"name":"Alice","age":30,"tags":["admin","user"]}';
var obj = JSON.parse(fromServer);
console.log(obj.name);   // "Alice"
console.log(obj.tags[0]); // "admin"

// JS object -> JSON string
var payload = { name: 'Bob', age: 25 };
var body = JSON.stringify(payload);
console.log(body);  // '{"name":"Bob","age":25}'

// Pretty-print with 2-space indent (handy for debugging)
console.log(JSON.stringify(payload, null, 2));

Reaching into deeply nested data. Modern JavaScript gives you a couple of nicer ways to dig into nested objects:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var response = {
  user: {
    profile: { name: 'Alice', address: null }
  }
};

// Old way — verbose, and crashes if any link is missing
var name = response.user.profile.name;

// Optional chaining (?.) — returns undefined instead of throwing
// when an intermediate value is null/undefined
var city = response.user?.profile?.address?.city;  // undefined, no error

// Destructuring — pull multiple fields out at once
var { name, profile: { address } } = response.user;

Optional chaining (?.) is especially useful when consuming JSON from an API where some fields are optional — you avoid a tower of if (foo && foo.bar && foo.bar.baz) guards.

Validating JSON. If you’re not sure whether a string is valid JSON, wrap the parse in try/catch — JSON.parse throws a SyntaxError on malformed input:

1
2
3
4
5
6
7
8
function safeParse(str) {
  try {
    return JSON.parse(str);
  } catch (e) {
    console.warn('Not valid JSON:', e.message);
    return null;
  }
}

For one-off command-line validation, the jq tool (or just python3 -m json.tool) will tell you exactly where the error is in the input — much friendlier than the parser’s line/column number.

Posted in javascript, Web Development | Comments Off on JSON Jumpstart

Vodafone Group, AT&T, and Verizon are The Biggest Yielding Companies In November 2011

Vodafone Group, the telecom giant known for its land line and wireless services around the U.S and U.K, together with two other U.S based telecom giants AT&T and Verizon are one of the best yielding companies in Nov 2011. As per today’s data, 2011-11-02, Vodafone is yielding 6.8% yearly, AT&T 5.9% and Verizon is 5.3%. Is this a good time to invest in these telecom companies? You might also want to see the list of stocks with the highest yield displayed in www.greenandredmarket.com‘s highest yield page.

Posted in Investment, Stock Market | Comments Off on Vodafone Group, AT&T, and Verizon are The Biggest Yielding Companies In November 2011

Biggest Companies in the USA (Top 30)

If you ever get interested with the top 30 biggest companies in the USA you can visit this link:
http://www.greenandredmarket.com/menu/biggestcompanies.htm
I’m really surprised that Apple‘s Market Capitalization is almost twice bigger than Microsoft

Posted in Investment, Stock Market | Comments Off on Biggest Companies in the USA (Top 30)