<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.leaky.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Leaky</id>
		<title>Leaky - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.leaky.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Leaky"/>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php/Special:Contributions/Leaky"/>
		<updated>2026-04-13T09:49:41Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=DKIM&amp;diff=410</id>
		<title>DKIM</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=DKIM&amp;diff=410"/>
				<updated>2024-03-05T21:50:43Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A simple script to generate the DKIM keys for a domain.&lt;br /&gt;
&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 &lt;br /&gt;
 DOMAIN=$1&lt;br /&gt;
 &lt;br /&gt;
 if [ ! -d /etc/exim/dkim ]&lt;br /&gt;
 then&lt;br /&gt;
     echo &amp;quot;No DKIM directory /etc/exim/dkim&amp;quot;&lt;br /&gt;
     exit&lt;br /&gt;
 fi&lt;br /&gt;
 cd /etc/exim/dkim &lt;br /&gt;
 &lt;br /&gt;
 if [ ! -f $DOMAIN.key ]&lt;br /&gt;
 then&lt;br /&gt;
     echo &amp;quot;Generating private key for $DOMAIN&amp;quot;&lt;br /&gt;
     openssl genrsa 4096 &amp;gt; $DOMAIN.key&lt;br /&gt;
 else&lt;br /&gt;
     echo &amp;quot;Private key for $DOMAIN already exists&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 if [ ! -f $DOMAIN.pub ]&lt;br /&gt;
 then&lt;br /&gt;
     echo &amp;quot;Generating public key for $DOMAIN&amp;quot;&lt;br /&gt;
     openssl rsa -in $DOMAIN.key -pubout &amp;gt; $DOMAIN.pub&lt;br /&gt;
 else&lt;br /&gt;
     echo &amp;quot;Public key for $DOMAIN already exists&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 chown root:exim $DOMAIN.key $DOMAIN.pub&lt;br /&gt;
 chmod 0640 $DOMAIN.key $DOMAIN.pub&lt;br /&gt;
 &lt;br /&gt;
 echo &amp;quot;TXT record required for $DOMAIN zonefile&amp;quot;&lt;br /&gt;
 echo &amp;quot;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 ./pub2txt.pl $DOMAIN.pub&lt;br /&gt;
&lt;br /&gt;
and the required pub2txt.pl converts a public key into a BIND record for your zone file.&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 &lt;br /&gt;
 my $f = shift @ARGV || die &amp;quot;Need filename&amp;quot;;&lt;br /&gt;
 my $key = &amp;quot;v=DKIM1; t=y; k=rsa; p=&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 open(PUB, &amp;quot;&amp;lt;&amp;quot;, $f) or die &amp;quot;Can't open file $f&amp;quot;;&lt;br /&gt;
 while (my $l = &amp;lt;PUB&amp;gt;) {&lt;br /&gt;
     chomp $l;&lt;br /&gt;
     next if ($l =~ /^----/);&lt;br /&gt;
     $key .= $l;&lt;br /&gt;
 }&lt;br /&gt;
 close(PUB);&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;s6122._domainkey\tIN\tTXT\t(\n&amp;quot;;&lt;br /&gt;
 print join &amp;quot;\n&amp;quot;, map { &amp;quot;\t\&amp;quot;$_\&amp;quot;&amp;quot; } $key =~ m[.{1,64}]g;&lt;br /&gt;
 print &amp;quot;\n\t)\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
After creating the DNS record and key files, simply ensure that the domain is configured for generating DKIM signatures - in my config, this involves adding a line to `/etc/exim/dkim/sender_domains` such as:&lt;br /&gt;
&lt;br /&gt;
 *@domain.com: domain.com&lt;br /&gt;
&lt;br /&gt;
The first field specifies which From addresses need to be signed and the value is the name of the key file to use in /etc/exim/dkim/&lt;br /&gt;
&lt;br /&gt;
[[Category:Email]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=DKIM&amp;diff=409</id>
		<title>DKIM</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=DKIM&amp;diff=409"/>
				<updated>2024-03-05T21:50:22Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot;A simple script to generate the DKIM keys for a domain.   #!/bin/bash    DOMAIN=$1    if [ ! -d /etc/exim/dkim ]  then      echo &amp;quot;No DKIM directory /etc/exim/dkim&amp;quot;      exit...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A simple script to generate the DKIM keys for a domain.&lt;br /&gt;
&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 &lt;br /&gt;
 DOMAIN=$1&lt;br /&gt;
 &lt;br /&gt;
 if [ ! -d /etc/exim/dkim ]&lt;br /&gt;
 then&lt;br /&gt;
     echo &amp;quot;No DKIM directory /etc/exim/dkim&amp;quot;&lt;br /&gt;
     exit&lt;br /&gt;
 fi&lt;br /&gt;
 cd /etc/exim/dkim &lt;br /&gt;
 &lt;br /&gt;
 if [ ! -f $DOMAIN.key ]&lt;br /&gt;
 then&lt;br /&gt;
     echo &amp;quot;Generating private key for $DOMAIN&amp;quot;&lt;br /&gt;
     openssl genrsa 4096 &amp;gt; $DOMAIN.key&lt;br /&gt;
 else&lt;br /&gt;
     echo &amp;quot;Private key for $DOMAIN already exists&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 if [ ! -f $DOMAIN.pub ]&lt;br /&gt;
 then&lt;br /&gt;
     echo &amp;quot;Generating public key for $DOMAIN&amp;quot;&lt;br /&gt;
     openssl rsa -in $DOMAIN.key -pubout &amp;gt; $DOMAIN.pub&lt;br /&gt;
 else&lt;br /&gt;
     echo &amp;quot;Public key for $DOMAIN already exists&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 chown root:exim $DOMAIN.key $DOMAIN.pub&lt;br /&gt;
 chmod 0640 $DOMAIN.key $DOMAIN.pub&lt;br /&gt;
 &lt;br /&gt;
 echo &amp;quot;TXT record required for $DOMAIN zonefile&amp;quot;&lt;br /&gt;
 echo &amp;quot;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 ./pub2txt.pl $DOMAIN.pub&lt;br /&gt;
&lt;br /&gt;
and the required pub2txt.pl converts a public key into a BIND record for your zone file.&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 &lt;br /&gt;
 my $f = shift @ARGV || die &amp;quot;Need filename&amp;quot;;&lt;br /&gt;
 my $key = &amp;quot;v=DKIM1; t=y; k=rsa; p=&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 open(PUB, &amp;quot;&amp;lt;&amp;quot;, $f) or die &amp;quot;Can't open file $f&amp;quot;;&lt;br /&gt;
 while (my $l = &amp;lt;PUB&amp;gt;) {&lt;br /&gt;
     chomp $l;&lt;br /&gt;
     next if ($l =~ /^----/);&lt;br /&gt;
     $key .= $l;&lt;br /&gt;
 }&lt;br /&gt;
 close(PUB);&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;s6122._domainkey\tIN\tTXT\t(\n&amp;quot;;&lt;br /&gt;
 print join &amp;quot;\n&amp;quot;, map { &amp;quot;\t\&amp;quot;$_\&amp;quot;&amp;quot; } $key =~ m[.{1,64}]g;&lt;br /&gt;
 print &amp;quot;\n\t)\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
After creating the DNS record and key files, simply ensure that the domain is configured for generating DKIM signatures - in my config, this involves adding a line to `/etc/exim/dkim/sender_domains` such as:&lt;br /&gt;
&lt;br /&gt;
 *@domain.com: domain.com&lt;br /&gt;
&lt;br /&gt;
The first field specifies which From addresses need to be signed and the value is the name of the key file to use in /etc/exim/dkim/&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Apache&amp;diff=408</id>
		<title>Apache</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Apache&amp;diff=408"/>
				<updated>2023-06-17T21:56:35Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* IP based redirect */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== IP based redirect ==&lt;br /&gt;
Apache virtualhost config to allow configuring of a Wordpress site while still redirecting the domain to some other site until Wordpress is ready.&lt;br /&gt;
&lt;br /&gt;
 ServerName www.example.com&lt;br /&gt;
 ServerAlias example.com&lt;br /&gt;
 ServerAdmin webmaster@example.com&lt;br /&gt;
 DocumentRoot /home/example/public_html/&lt;br /&gt;
 &lt;br /&gt;
 RewriteEngine On&lt;br /&gt;
 # Replace 1.2.3.4 with the IP setting up the site&lt;br /&gt;
 RewriteCond %{REMOTE_ADDR} =1.2.3.4&lt;br /&gt;
 RewriteRule &amp;quot;.?&amp;quot; &amp;quot;-&amp;quot; [L]&lt;br /&gt;
 &lt;br /&gt;
 # Everyone other than 1.2.3.4 gets redirected to example.wordpress.com&lt;br /&gt;
 RewriteCond %{SERVER_NAME} =example.com [OR]&lt;br /&gt;
 RewriteCond %{SERVER_NAME} =www.example.com&lt;br /&gt;
 RewriteRule ^ https://example.wordpress.com%{REQUEST_URI} [NE,R=temp,L]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Apache&amp;diff=407</id>
		<title>Apache</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Apache&amp;diff=407"/>
				<updated>2023-06-17T21:56:25Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot; == IP based redirect == Apache virtualhost config to allow configuring of a Wordpress site while still redirecting the domain to some other site until Wordpress is ready.   S...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== IP based redirect ==&lt;br /&gt;
Apache virtualhost config to allow configuring of a Wordpress site while still redirecting the domain to some other site until Wordpress is ready.&lt;br /&gt;
&lt;br /&gt;
 ServerName www.example.com&lt;br /&gt;
 ServerAlias example.com&lt;br /&gt;
 ServerAdmin webmaster@example.com&lt;br /&gt;
 DocumentRoot /home/example/public_html/&lt;br /&gt;
&lt;br /&gt;
 RewriteEngine On&lt;br /&gt;
 # Replace 1.2.3.4 with the IP setting up the site&lt;br /&gt;
 RewriteCond %{REMOTE_ADDR} =1.2.3.4&lt;br /&gt;
 RewriteRule &amp;quot;.?&amp;quot; &amp;quot;-&amp;quot; [L]&lt;br /&gt;
&lt;br /&gt;
 # Everyone other than 1.2.3.4 gets redirected to example.wordpress.com&lt;br /&gt;
 RewriteCond %{SERVER_NAME} =example.com [OR]&lt;br /&gt;
 RewriteCond %{SERVER_NAME} =www.example.com&lt;br /&gt;
 RewriteRule ^ https://example.wordpress.com%{REQUEST_URI} [NE,R=temp,L]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Firewalld&amp;diff=406</id>
		<title>Firewalld</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Firewalld&amp;diff=406"/>
				<updated>2022-05-01T23:53:35Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Port forwarding */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== IPv6 as a 'public' interface ==&lt;br /&gt;
&lt;br /&gt;
 firewall-cmd --zone=public --add-interface=sit1&lt;br /&gt;
&lt;br /&gt;
== Setting specific source IPs to a zone ==&lt;br /&gt;
&lt;br /&gt;
This should make any traffic from 10.0.0.0/24 be associated with a zone called 'work'. This would allow (for example) http, https and ssh to be accepted, but not other services - even if they came in on an interface that was linked to a different zone.&lt;br /&gt;
&lt;br /&gt;
 firewall-cmd --zone=work --add-source=&amp;quot;10.0.0.0/24&amp;quot;&lt;br /&gt;
 firewall-cmd --zone=work --add-service=ssh&lt;br /&gt;
 firewall-cmd --zone=work --add-service=http&lt;br /&gt;
 firewall-cmd --zone=work --add-service=https&lt;br /&gt;
&lt;br /&gt;
== Port forwarding ==&lt;br /&gt;
&lt;br /&gt;
firewalld is configured on host12 with two zones: public and dmz&lt;br /&gt;
&lt;br /&gt;
* Public network is configured as 192.168.1.12/24 (would normally be a public IP)&lt;br /&gt;
* DMZ network is configured as 172.16.4.12/24&lt;br /&gt;
&lt;br /&gt;
ssh to 192.168.1.12 gets access to host12 as expected because of the default [[CentOS7]] config.&lt;br /&gt;
&lt;br /&gt;
 firewall-cmd --zone=public --add-service=ssh&lt;br /&gt;
&lt;br /&gt;
firewalld is configured on host14 with one zone: public - even though the actual interface is connected to the DMZ network.&lt;br /&gt;
&lt;br /&gt;
* Public network is configured as 172.16.4.14/24&lt;br /&gt;
&lt;br /&gt;
Ideally, we want to connect to port 22 on a host12 IP alias and be forwarded to port 22 on host14. This principle can be extended to other services such as http/https so that there's no proxying required.&lt;br /&gt;
&lt;br /&gt;
Add another IP to host12 as an IP alias on the public network (e.g ens33:0), we'll use 192.168.1.14/24 to make it obvious. &lt;br /&gt;
&lt;br /&gt;
 ip address add 192.168.1.14/24 dev ens33:0&lt;br /&gt;
&lt;br /&gt;
Now this IP pings but if you ssh to it you'll end up on host12. Add the following two commands and ssh to 192.168.1.14 connects you to host14 instead. ssh to 192.168.1.12 still goes to host12 as expected.&lt;br /&gt;
&lt;br /&gt;
 firewall-cmd --zone=public --add-rich-rule=&amp;quot;rule family='ipv4'&lt;br /&gt;
    destination address='192.168.1.14' forward-port port='22'&lt;br /&gt;
    protocol='tcp' to-addr='172.16.4.14'&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 firewall-cmd --zone=dmz --add-masquerade&lt;br /&gt;
&lt;br /&gt;
The masquerading is added to the dmz zone because anything going out to network addresses in the dmz needs to be masqueraded.&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=PowerDNS&amp;diff=405</id>
		<title>PowerDNS</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=PowerDNS&amp;diff=405"/>
				<updated>2022-04-06T15:29:12Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
On Debian, install the relevant packages. At time of writing, this is version 4.1.6&lt;br /&gt;
&lt;br /&gt;
 apt-get install pdns-server pdns-backend-sqlite3&lt;br /&gt;
 apt-get install sqlite3&lt;br /&gt;
 apt-get remove pdns-backend-bind&lt;br /&gt;
&lt;br /&gt;
Remove the bind backend config (as of 4.1.6 it doesn't support slave configs managed through pdnsutil) and create one for SQLite3.&lt;br /&gt;
&lt;br /&gt;
 rm /etc/powerdns/pdns.d/bind.conf&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/powerdns/pdns.d/sqlite3.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 launch += gsqlite3&lt;br /&gt;
 gsqlite3-database=/var/lib/powerdns/powerdns.sqlite3&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Update the main config to enable slave mode:&lt;br /&gt;
&lt;br /&gt;
 (UNTESTED) perl -spi -le 's/^# slave=yes/slave=yes/' /etc/powerdns/pdns.conf&lt;br /&gt;
&lt;br /&gt;
Make sure there's a line uncommented saying &amp;quot;slave=yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Create the SQLite3 database and fix permissions&lt;br /&gt;
&lt;br /&gt;
 sqlite3 /var/lib/powerdns/powerdns.sqlite3 &amp;lt; /usr/share/pdns-backend-sqlite3/schema/schema.sqlite3.sql&lt;br /&gt;
 chown pdns: /var/lib/powerdns /var/lib/powerdns/powerdns.sqlite3&lt;br /&gt;
&lt;br /&gt;
Restart the service&lt;br /&gt;
&lt;br /&gt;
 systemctl restart pdns&lt;br /&gt;
&lt;br /&gt;
Set it to start automatically&lt;br /&gt;
&lt;br /&gt;
 systemctl enable pdns&lt;br /&gt;
&lt;br /&gt;
Assuming it comes up ok, you can add slave zones with the following command:&lt;br /&gt;
&lt;br /&gt;
 pdnsutil create-slave-zone bocks.com 78.129.196.11&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Docker&amp;diff=404</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Docker&amp;diff=404"/>
				<updated>2021-10-11T11:22:55Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation of Docker on CentOS7 ==&lt;br /&gt;
&lt;br /&gt;
Use the docker-ce (community edition) packages rather than whatever might come with the OS or EPEL.&lt;br /&gt;
&lt;br /&gt;
 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo&lt;br /&gt;
 yum install docker-ce docker-compose&lt;br /&gt;
&lt;br /&gt;
 systemctl start docker&lt;br /&gt;
 systemctl enable docker&lt;br /&gt;
 docker run hello-world&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Installing&amp;quot; docker-compose (downloading the script)&lt;br /&gt;
&lt;br /&gt;
 curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose&lt;br /&gt;
 chmod +x /usr/local/bin/docker-compose&lt;br /&gt;
&lt;br /&gt;
== Assorted links ==&lt;br /&gt;
&lt;br /&gt;
A 5+bonus part guide to developing using docker - https://lockmedown.com/docker-4-devs-containerizing-app/&lt;br /&gt;
&lt;br /&gt;
See also [[Flynn]] which can provision apps using docker images.&lt;br /&gt;
&lt;br /&gt;
http://blog.dubizzle.com/boilerroom/2016/08/18/setting-development-environment-docker-compose/&lt;br /&gt;
https://docs.docker.com/compose/wordpress/&lt;br /&gt;
https://hub.docker.com/_/php/&lt;br /&gt;
&lt;br /&gt;
== Sample Dockerfile which builds an Apache container ==&lt;br /&gt;
&lt;br /&gt;
 cat &amp;gt; Dockerfile &amp;lt;&amp;lt;'EOF'&lt;br /&gt;
 FROM php:7.2-apache&lt;br /&gt;
 # RUN docker-php-ext-install&lt;br /&gt;
 COPY php-shop.ini /tmp/etc/php.d/shop.ini&lt;br /&gt;
 ENV APACHE_DOCUMENT_ROOT /home/docker1/public_html&lt;br /&gt;
 RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf&lt;br /&gt;
 RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf&lt;br /&gt;
 RUN sed -ri -e 's!User www-data!User shop!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf&lt;br /&gt;
 RUN sed -ri -e 's!Group www-data!Group shop!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Build the image&lt;br /&gt;
&lt;br /&gt;
 docker build -t testshop .&lt;br /&gt;
&lt;br /&gt;
Create the container from the new image. This uses port 8010 for the web server and mounts /home/docker1/public_html from the host into the container&lt;br /&gt;
&lt;br /&gt;
 docker create --name myshopcontainer -it -p 8010:80/tcp --mount type=bind,source=/home/docker1/public_html,target=/home/docker1/public_html testshop:latest&lt;br /&gt;
&lt;br /&gt;
Start the container&lt;br /&gt;
&lt;br /&gt;
 docker start myshopcontainer&lt;br /&gt;
&lt;br /&gt;
== Other commands ==&lt;br /&gt;
&lt;br /&gt;
Show all the containers that currently exist on the host&lt;br /&gt;
&lt;br /&gt;
 docker container list --all&lt;br /&gt;
&lt;br /&gt;
Remove '''all''' stopped containers&lt;br /&gt;
&lt;br /&gt;
 docker container prune&lt;br /&gt;
&lt;br /&gt;
List all images that are available in the cache&lt;br /&gt;
&lt;br /&gt;
 docker image list&lt;br /&gt;
&lt;br /&gt;
Remove an image from the host cache&lt;br /&gt;
&lt;br /&gt;
 docker image rm NAME&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Docker containers unable to access services on host ==&lt;br /&gt;
&lt;br /&gt;
Copied from https://github.com/moby/moby/issues/16137#issuecomment-271615192 as it took me a while to find.&lt;br /&gt;
&lt;br /&gt;
=== The ultra short version of the fix ===&lt;br /&gt;
&lt;br /&gt;
Run all these commands&lt;br /&gt;
&lt;br /&gt;
 nmcli connection modify docker0 connection.zone trusted&lt;br /&gt;
 systemctl stop NetworkManager.service&lt;br /&gt;
 firewall-cmd --permanent --zone=trusted --change-interface=docker0&lt;br /&gt;
 systemctl start NetworkManager.service&lt;br /&gt;
 nmcli connection modify docker0 connection.zone trusted&lt;br /&gt;
 systemctl restart docker.service&lt;br /&gt;
&lt;br /&gt;
=== The explained version and how to check everything worked ===&lt;br /&gt;
&lt;br /&gt;
The current workaround that seems to work ends up creating a trusted.xml file AND a ifcfg-docker0 file. The trusted.xml file would set the zone after a reboot (read and used by firewalld) and the ifcfg-docker0 would set the zone after reload or restart of services and interface or connections restarted (read and used mainly by NetworkManager).&lt;br /&gt;
&lt;br /&gt;
To achieve that:&lt;br /&gt;
* After having the new interface (e.g. after installing Docker) and having FirewallD enabled and started, set the zone of the interface with NetworkManager's nmcli:&lt;br /&gt;
&lt;br /&gt;
 nmcli connection modify docker0 connection.zone trusted&lt;br /&gt;
&lt;br /&gt;
...that would set the zone in NetworkManager and FirewallD for the current session and will create the ifcfg-docker0 file for services, network or interfaces' restarts and reloads.&lt;br /&gt;
&lt;br /&gt;
* Check that the file was created with:&lt;br /&gt;
&lt;br /&gt;
 cat /etc/sysconfig/network-scripts/ifcfg-docker0&lt;br /&gt;
&lt;br /&gt;
...it should output something like:&lt;br /&gt;
&lt;br /&gt;
 DEVICE=docker0&lt;br /&gt;
 STP=no&lt;br /&gt;
 BRIDGING_OPTS=ageing_time=299&lt;br /&gt;
 TYPE=Bridge&lt;br /&gt;
 BOOTPROTO=none&lt;br /&gt;
 IPADDR=172.17.0.1&lt;br /&gt;
 PREFIX=16&lt;br /&gt;
 DEFROUTE=yes&lt;br /&gt;
 IPV4_FAILURE_FATAL=no&lt;br /&gt;
 IPV6INIT=no&lt;br /&gt;
 NAME=docker0&lt;br /&gt;
 UUID=5ccc8292-95a2-40d5-9ed6-ab6202fa629e&lt;br /&gt;
 ONBOOT=no&lt;br /&gt;
 ZONE=trusted&lt;br /&gt;
&lt;br /&gt;
...specifically, it should have a:&lt;br /&gt;
&lt;br /&gt;
 ZONE=trusted&lt;br /&gt;
&lt;br /&gt;
* Now we need FirewallD to generate that trusted.xml file so that it uses it while booting, but for FirewallD to write that file it must think that NetworkManager is not active, so stop NetworkManager:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop NetworkManager.service&lt;br /&gt;
&lt;br /&gt;
* Now set the zone with FirewallD's firewall-cmd:&lt;br /&gt;
&lt;br /&gt;
 firewall-cmd --permanent --zone=trusted --change-interface=docker0&lt;br /&gt;
&lt;br /&gt;
* As NetworkManager is stopped, it won't modify (or even try to create) an ifcfg-docker0 file, if NetworkManager was running it would try to create that same file and wouldn't work after reboot. But this time, as Networkmanager is stopped, it will create a file in the other place for configurations, we can see it with:&lt;br /&gt;
&lt;br /&gt;
 cat /etc/firewalld/zones/trusted.xml&lt;br /&gt;
&lt;br /&gt;
...outputs:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;
 &amp;lt;zone target=&amp;quot;ACCEPT&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;short&amp;gt;Trusted&amp;lt;/short&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;All network connections are accepted.&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;interface name=&amp;quot;docker0&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/zone&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...we can see that the docker0 interface was added to this trusted zone by the:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;interface name=&amp;quot;docker0&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* And now we can start NetworkManager again:&lt;br /&gt;
&lt;br /&gt;
 systemctl start NetworkManager.service&lt;br /&gt;
&lt;br /&gt;
* It is possible that you need to set the zone with NetworkManager again as firewalld might have &amp;quot;forgotten&amp;quot; the zone settings, it won't do any harm:&lt;br /&gt;
&lt;br /&gt;
 nmcli connection modify docker0 connection.zone trusted&lt;br /&gt;
&lt;br /&gt;
* We can check that FirewallD thinks that the docker0 is in the trusted zone. Check the zone of the docker0 interface as seen by FirewallD:&lt;br /&gt;
&lt;br /&gt;
 firewall-cmd --get-zone-of-interface=docker0&lt;br /&gt;
&lt;br /&gt;
...outputs:&lt;br /&gt;
&lt;br /&gt;
 trusted&lt;br /&gt;
&lt;br /&gt;
* And NetworkManager also thinks that it is in the trusted zone. Check the zone of the docker0 interface as seen by NetworkManager:&lt;br /&gt;
&lt;br /&gt;
 nmcli connection show docker0 | grep zone&lt;br /&gt;
&lt;br /&gt;
...outputs something like:&lt;br /&gt;
&lt;br /&gt;
 connection.zone:                        trusted&lt;br /&gt;
&lt;br /&gt;
* We can restart the system and check that the zone will persist, for both FirewallD and NetworkManager.&lt;br /&gt;
&lt;br /&gt;
* If you already checked that it worked and don't want to restart the system, you still will have to restart the Docker service for it to re-create it's ipatables rules:&lt;br /&gt;
&lt;br /&gt;
 systemctl restart docker.service&lt;br /&gt;
&lt;br /&gt;
* If you need to change more things with FirewallD and NetworkManager, or if something doesn't seem to be working, please read that issue in FirewallD, as here I'm not showing a lot of the details: https://github.com/t-woerner/firewalld/issues/195&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Windows10&amp;diff=403</id>
		<title>Windows10</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Windows10&amp;diff=403"/>
				<updated>2021-10-08T12:44:41Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Enabling the Windows 10 lock screen image information ==&lt;br /&gt;
&lt;br /&gt;
Click on Start &amp;gt; Run and type '''control userpasswords2''' to open the user management dialog. Click on the Advanced tab and untick the checkbox at the bottom for ''Require users to press Ctrl-Alt-Delete''&lt;br /&gt;
&lt;br /&gt;
== Disable Bing search for everything ==&lt;br /&gt;
&lt;br /&gt;
In the registry:&lt;br /&gt;
&lt;br /&gt;
 Computer\HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Explorer\DisableSearchBoxSuggestions = 1&lt;br /&gt;
&lt;br /&gt;
Restart the Windows Explorer process (or logout and back in)&lt;br /&gt;
&lt;br /&gt;
== Remove the 3D Objects folder from Explorer ==&lt;br /&gt;
&lt;br /&gt;
Press WIN+R key and type regedit&lt;br /&gt;
&lt;br /&gt;
From both of the following locations:&lt;br /&gt;
&lt;br /&gt;
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace&lt;br /&gt;
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace&lt;br /&gt;
&lt;br /&gt;
Delete the path and contents called:&lt;br /&gt;
&lt;br /&gt;
 {0DB7E03F-FC29-4DC6-9020-FF41B59E513A}&lt;br /&gt;
&lt;br /&gt;
Close all your Explorer windows and re-open one. The 3D Objects folder should be gone.&lt;br /&gt;
&lt;br /&gt;
== Comparison of files or folders ==&lt;br /&gt;
&lt;br /&gt;
Install '''WinMerge''' from [http://winmerge.org/ winmerge.org] - it includes a shell extension to allow easy comparison of files or folders.&lt;br /&gt;
&lt;br /&gt;
== View image EXIF data ==&lt;br /&gt;
&lt;br /&gt;
Picture Information Extractor (PIE) - free download&lt;br /&gt;
&lt;br /&gt;
* [https://www.picmeta.com/download.htm picmeta.com]&lt;br /&gt;
&lt;br /&gt;
== Checksum files ==&lt;br /&gt;
&lt;br /&gt;
Works in Windows 7 and 8 too.&lt;br /&gt;
&lt;br /&gt;
 certutil -HashFile filename.zip MD5&lt;br /&gt;
 certutil -HashFile filename.zip SHA1&lt;br /&gt;
&lt;br /&gt;
== MacOS QuickLook for Windows ==&lt;br /&gt;
&lt;br /&gt;
It allows user peek into a file content in lightning speed by just pressing the Space key.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/QL-Win/QuickLook QuickLook for Windows]&lt;br /&gt;
&lt;br /&gt;
== Ditto - multi-buffer clipboard ==&lt;br /&gt;
&lt;br /&gt;
[https://ditto-cp.sourceforge.io/ Direct from SourceForge] or via the [https://www.microsoft.com/en-us/p/ditto-clipboard/9nblggh3zbjq Microsoft Store]&lt;br /&gt;
&lt;br /&gt;
== Multi-monitor Remote Desktop not working? ==&lt;br /&gt;
&lt;br /&gt;
In the group policy (gpedit) check:&lt;br /&gt;
&lt;br /&gt;
Computer Configuration&lt;br /&gt;
-&amp;gt; Administrative Templates&lt;br /&gt;
-&amp;gt; System&lt;br /&gt;
-&amp;gt; Windows Components&lt;br /&gt;
-&amp;gt; Remote Desktop Services&lt;br /&gt;
-&amp;gt; Remote Desktop Session Host&lt;br /&gt;
-&amp;gt; Remote Desktop Environment&lt;br /&gt;
-&amp;gt; limit maximum number of monitors&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=PowerDNS&amp;diff=402</id>
		<title>PowerDNS</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=PowerDNS&amp;diff=402"/>
				<updated>2021-09-17T21:55:50Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot; On Debian, install the relevant packages. At time of writing, this is version 4.1.6   apt-get install pdns-server pdns-backend-sqlite3  apt-get install sqlite3  apt-get remov...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
On Debian, install the relevant packages. At time of writing, this is version 4.1.6&lt;br /&gt;
&lt;br /&gt;
 apt-get install pdns-server pdns-backend-sqlite3&lt;br /&gt;
 apt-get install sqlite3&lt;br /&gt;
 apt-get remove pdns-backend-bind&lt;br /&gt;
&lt;br /&gt;
Remove the bind backend config (as of 4.1.6 it doesn't support slave configs managed through pdnsutil) and create one for SQLite3.&lt;br /&gt;
&lt;br /&gt;
 rm /etc/powerdns/pdns.d/bind.conf&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/powerdns/pdns.d/sqlite3.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 launch += gsqlite3&lt;br /&gt;
 gsqlite3-database=/var/lib/powerdns/powerdns.sqlite3&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Update the main config to enable slave mode:&lt;br /&gt;
&lt;br /&gt;
 (UNTESTED) perl -spi -le 's/^# slave=yes/slave=yes/' /etc/powerdns/pdns.conf&lt;br /&gt;
&lt;br /&gt;
Make sure there's a line uncommented saying &amp;quot;slave=yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Create the SQLite3 database and fix permissions&lt;br /&gt;
&lt;br /&gt;
 sqlite3 /var/lib/powerdns/powerdns.sqlite3 &amp;lt; /usr/share/pdns-backend-sqlite3/schema/schema.sqlite3.sql&lt;br /&gt;
 chown pdns: /var/lib/powerdns /var/lib/powerdns/powerdns.sqlite3&lt;br /&gt;
&lt;br /&gt;
Restart the service&lt;br /&gt;
&lt;br /&gt;
 systemctl restart pdns&lt;br /&gt;
&lt;br /&gt;
Assuming it comes up ok, you can add slave zones with the following command:&lt;br /&gt;
&lt;br /&gt;
 pdnsutil create-slave-zone bocks.com 78.129.196.11&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Iptables&amp;diff=401</id>
		<title>Iptables</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Iptables&amp;diff=401"/>
				<updated>2021-08-28T23:40:31Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To forward packets sent to one IP over to a different IP on a different server, you can use iptables.&lt;br /&gt;
&lt;br /&gt;
 OLD_IP=92.48.119.131&lt;br /&gt;
 NEW_IP=213.229.103.79&lt;br /&gt;
 &lt;br /&gt;
 OLD_PORT=80&lt;br /&gt;
 NEW_PORT=80&lt;br /&gt;
&lt;br /&gt;
 iptables -t nat -A PREROUTING -d $OLD_IP -p tcp -m tcp --dport $OLD_PORT -j DNAT --to-destination $NEW_IP:$NEW_PORT&lt;br /&gt;
 iptables -t nat -A POSTROUTING ! -s $OLD_IP -d $NEW_IP -p tcp -m tcp --dport $NEW_PORT -j SNAT --to-source $OLD_IP&lt;br /&gt;
&lt;br /&gt;
Blanket allow all packets being forwarded to the new IP.&lt;br /&gt;
&lt;br /&gt;
 iptables -I FORWARD -d $NEW_IP -j ACCEPT&lt;br /&gt;
 iptables -I FORWARD -s $NEW_IP -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
Things to watch for if it doesn't work - IP forwarding needs to be enabled (''sysctl -w net.ipv4.ip_forward=1'') and you may need to allow the specific port in the INPUT chain. Not sure about this as I had already allowed port 80 prior to setting up the forwarding.&lt;br /&gt;
&lt;br /&gt;
[[Category:Networks]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=LVM&amp;diff=400</id>
		<title>LVM</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=LVM&amp;diff=400"/>
				<updated>2021-07-16T10:29:01Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* rescan the scsi bus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== rescan the scsi bus ==&lt;br /&gt;
&lt;br /&gt;
If you've added another virtual disk to a VM, it may not see it without a reboot. If that's not going to be convenient it may show up by rescanning the scsi bus.&lt;br /&gt;
&lt;br /&gt;
 # echo &amp;quot;- - -&amp;quot; &amp;gt; /sys/class/scsi_host/host0/scan&lt;br /&gt;
&lt;br /&gt;
It may not be host0 so check what's available. After this the new drive should show up.&lt;br /&gt;
&lt;br /&gt;
If you simply increased the size of the existing disk, you can try:&lt;br /&gt;
&lt;br /&gt;
 # echo 1 &amp;gt; /sys/block/sda/device/rescan&lt;br /&gt;
&lt;br /&gt;
This should make it show the new size via the command&lt;br /&gt;
&lt;br /&gt;
 # fdisk -l /dev/sda&lt;br /&gt;
&lt;br /&gt;
== Creating new volumes ==&lt;br /&gt;
&lt;br /&gt;
Assuming that &amp;lt;code&amp;gt;/dev/sdb&amp;lt;/code&amp;gt; is a new disk with a single full size partition &amp;lt;code&amp;gt;/dev/sdb1&amp;lt;/code&amp;gt;, the following will create a new volume group called &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; and a couple of logical volumes inside called &amp;lt;code&amp;gt;projects&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;backups&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # vgcreate data /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # lvcreate -n projects -L 20G data&lt;br /&gt;
 # lvcreate -n backups -l 100%FREE data&lt;br /&gt;
&lt;br /&gt;
== Extending a filesystem to include a new partition ==&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT: Check the partitions, do not just copy/paste below!'''&lt;br /&gt;
&lt;br /&gt;
Initialise the LVM metadata on the partition to add into the filesystem&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
&lt;br /&gt;
Add the partition to the volume group&lt;br /&gt;
&lt;br /&gt;
 # vgextend sys /dev/sdb1&lt;br /&gt;
   Volume group &amp;quot;sys&amp;quot; successfully extended&lt;br /&gt;
&lt;br /&gt;
Extend the relevant logical volume to include all of the newly added space&lt;br /&gt;
&lt;br /&gt;
 # lvextend -l +100%FREE /dev/sys/root&lt;br /&gt;
  Size of logical volume sys/root changed from 27.88 GiB (892 extents) to 47.84 GiB (1531 extents).&lt;br /&gt;
  Logical volume root successfully resized&lt;br /&gt;
&lt;br /&gt;
Resize the underlying filesystem to use the whole LVM device&lt;br /&gt;
&lt;br /&gt;
 # resize2fs /dev/sys/root&lt;br /&gt;
 resize2fs 1.41.12 (17-May-2010)&lt;br /&gt;
 Filesystem at /dev/sys/root is mounted on /; on-line resizing required&lt;br /&gt;
 old desc_blocks = 2, new_desc_blocks = 3&lt;br /&gt;
 Performing an on-line resize of /dev/sys/root to 12541952 (4k) blocks.&lt;br /&gt;
 The filesystem on /dev/sys/root is now 12541952 blocks long.&lt;br /&gt;
&lt;br /&gt;
== Mounting a filesystem from a Xen disk file that has LVM on it ==&lt;br /&gt;
&lt;br /&gt;
 # losetup /dev/loop7 xenguest1.xvda.img&lt;br /&gt;
 # kpartx -v -a xenguest1.xvda.img&lt;br /&gt;
&lt;br /&gt;
If the disk partitions were just normal ones, you would be able to mount them now as /dev/loop7p1 /dev/loop7p2 etc. If the filesystems are contained within an LVM volume group there are some extra steps.&lt;br /&gt;
&lt;br /&gt;
Scan physical volumes for LVM partitions&lt;br /&gt;
&lt;br /&gt;
 # pvscan&lt;br /&gt;
 PV /dev/mapper/loop7p2   VG vg_xenguest1  lvm2 [29.51 GiB / 0    free]&lt;br /&gt;
&lt;br /&gt;
Scan the partitions for volume groups&lt;br /&gt;
&lt;br /&gt;
 # vgscan&lt;br /&gt;
 Reading all physical volumes.  This may take a while...&lt;br /&gt;
 Found volume group &amp;quot;vg_xenguest1&amp;quot; using metadata type lvm2&lt;br /&gt;
&lt;br /&gt;
Scan for logical volumes. Any that are currently in use will show ACTIVE in the first column.&lt;br /&gt;
&lt;br /&gt;
 # lvscan&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_root' [28.54 GiB] inherit&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_swap' [992.00 MiB] inherit&lt;br /&gt;
&lt;br /&gt;
Since these are inactive, they can't be used as devices (yet).&lt;br /&gt;
&lt;br /&gt;
 # lvdisplay /dev/vg_xenguest1/lv_root&lt;br /&gt;
 ...&lt;br /&gt;
  LV Status              NOT available&lt;br /&gt;
  LV Size                28.54 GiB&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
First we need to set the volume group active, and then the logical volumes should work fine.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -ay vg_xenguest1&lt;br /&gt;
 2 logical volume(s) in volume group &amp;quot;vg_xenguest1&amp;quot; now active&lt;br /&gt;
&lt;br /&gt;
And now we can mount the root filesystem.&lt;br /&gt;
&lt;br /&gt;
 # mkdir /mnt/xenguest1&lt;br /&gt;
 # mount -t ext3 /dev/mapper/vg_xenguest1/lv_root /mnt/xenguest1&lt;br /&gt;
&lt;br /&gt;
When you're finished with it, use the following commands to make the volumes inactive, remove the partitions from the kernel partition map and then remove the loopback device.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -an vg_xenguest1 &lt;br /&gt;
 # kpartx -v -d /dev/loop7&lt;br /&gt;
 # losetup -d /dev/loop7&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=LVM&amp;diff=399</id>
		<title>LVM</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=LVM&amp;diff=399"/>
				<updated>2021-07-16T10:28:42Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* rescan the scsi bus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== rescan the scsi bus ==&lt;br /&gt;
&lt;br /&gt;
If you've added another virtual disk to a VM, it may not see it without a reboot. If that's not going to be convenient it may show up by rescanning the scsi bus.&lt;br /&gt;
&lt;br /&gt;
 # echo &amp;quot;- - -&amp;quot; &amp;gt; /sys/class/scsi_host/host0/scan&lt;br /&gt;
&lt;br /&gt;
It may not be host0 so check what's available. After this the new drive should show up.&lt;br /&gt;
&lt;br /&gt;
If you simply increased the size of the existing disk, you can try:&lt;br /&gt;
&lt;br /&gt;
 # echo 1 &amp;gt; /sys/block/sda/device/rescan&lt;br /&gt;
&lt;br /&gt;
This should make it show the new size via&lt;br /&gt;
&lt;br /&gt;
 fdisk -l /dev/sda&lt;br /&gt;
&lt;br /&gt;
== Creating new volumes ==&lt;br /&gt;
&lt;br /&gt;
Assuming that &amp;lt;code&amp;gt;/dev/sdb&amp;lt;/code&amp;gt; is a new disk with a single full size partition &amp;lt;code&amp;gt;/dev/sdb1&amp;lt;/code&amp;gt;, the following will create a new volume group called &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; and a couple of logical volumes inside called &amp;lt;code&amp;gt;projects&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;backups&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # vgcreate data /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # lvcreate -n projects -L 20G data&lt;br /&gt;
 # lvcreate -n backups -l 100%FREE data&lt;br /&gt;
&lt;br /&gt;
== Extending a filesystem to include a new partition ==&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT: Check the partitions, do not just copy/paste below!'''&lt;br /&gt;
&lt;br /&gt;
Initialise the LVM metadata on the partition to add into the filesystem&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
&lt;br /&gt;
Add the partition to the volume group&lt;br /&gt;
&lt;br /&gt;
 # vgextend sys /dev/sdb1&lt;br /&gt;
   Volume group &amp;quot;sys&amp;quot; successfully extended&lt;br /&gt;
&lt;br /&gt;
Extend the relevant logical volume to include all of the newly added space&lt;br /&gt;
&lt;br /&gt;
 # lvextend -l +100%FREE /dev/sys/root&lt;br /&gt;
  Size of logical volume sys/root changed from 27.88 GiB (892 extents) to 47.84 GiB (1531 extents).&lt;br /&gt;
  Logical volume root successfully resized&lt;br /&gt;
&lt;br /&gt;
Resize the underlying filesystem to use the whole LVM device&lt;br /&gt;
&lt;br /&gt;
 # resize2fs /dev/sys/root&lt;br /&gt;
 resize2fs 1.41.12 (17-May-2010)&lt;br /&gt;
 Filesystem at /dev/sys/root is mounted on /; on-line resizing required&lt;br /&gt;
 old desc_blocks = 2, new_desc_blocks = 3&lt;br /&gt;
 Performing an on-line resize of /dev/sys/root to 12541952 (4k) blocks.&lt;br /&gt;
 The filesystem on /dev/sys/root is now 12541952 blocks long.&lt;br /&gt;
&lt;br /&gt;
== Mounting a filesystem from a Xen disk file that has LVM on it ==&lt;br /&gt;
&lt;br /&gt;
 # losetup /dev/loop7 xenguest1.xvda.img&lt;br /&gt;
 # kpartx -v -a xenguest1.xvda.img&lt;br /&gt;
&lt;br /&gt;
If the disk partitions were just normal ones, you would be able to mount them now as /dev/loop7p1 /dev/loop7p2 etc. If the filesystems are contained within an LVM volume group there are some extra steps.&lt;br /&gt;
&lt;br /&gt;
Scan physical volumes for LVM partitions&lt;br /&gt;
&lt;br /&gt;
 # pvscan&lt;br /&gt;
 PV /dev/mapper/loop7p2   VG vg_xenguest1  lvm2 [29.51 GiB / 0    free]&lt;br /&gt;
&lt;br /&gt;
Scan the partitions for volume groups&lt;br /&gt;
&lt;br /&gt;
 # vgscan&lt;br /&gt;
 Reading all physical volumes.  This may take a while...&lt;br /&gt;
 Found volume group &amp;quot;vg_xenguest1&amp;quot; using metadata type lvm2&lt;br /&gt;
&lt;br /&gt;
Scan for logical volumes. Any that are currently in use will show ACTIVE in the first column.&lt;br /&gt;
&lt;br /&gt;
 # lvscan&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_root' [28.54 GiB] inherit&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_swap' [992.00 MiB] inherit&lt;br /&gt;
&lt;br /&gt;
Since these are inactive, they can't be used as devices (yet).&lt;br /&gt;
&lt;br /&gt;
 # lvdisplay /dev/vg_xenguest1/lv_root&lt;br /&gt;
 ...&lt;br /&gt;
  LV Status              NOT available&lt;br /&gt;
  LV Size                28.54 GiB&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
First we need to set the volume group active, and then the logical volumes should work fine.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -ay vg_xenguest1&lt;br /&gt;
 2 logical volume(s) in volume group &amp;quot;vg_xenguest1&amp;quot; now active&lt;br /&gt;
&lt;br /&gt;
And now we can mount the root filesystem.&lt;br /&gt;
&lt;br /&gt;
 # mkdir /mnt/xenguest1&lt;br /&gt;
 # mount -t ext3 /dev/mapper/vg_xenguest1/lv_root /mnt/xenguest1&lt;br /&gt;
&lt;br /&gt;
When you're finished with it, use the following commands to make the volumes inactive, remove the partitions from the kernel partition map and then remove the loopback device.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -an vg_xenguest1 &lt;br /&gt;
 # kpartx -v -d /dev/loop7&lt;br /&gt;
 # losetup -d /dev/loop7&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Git&amp;diff=398</id>
		<title>Git</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Git&amp;diff=398"/>
				<updated>2021-05-13T09:19:02Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Merging a branch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellpadding=10 align=right&lt;br /&gt;
| __TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Writing Good Commit Messages ==&lt;br /&gt;
&lt;br /&gt;
There are just two rules for writing good commit messages.&lt;br /&gt;
&lt;br /&gt;
# '''DO NOT''' just put &amp;quot;bugfix&amp;quot; or &amp;quot;updated this&amp;quot;&lt;br /&gt;
# '''Limit the commit message to approx 50 characters'''&lt;br /&gt;
&lt;br /&gt;
Unless it is immediately obvious what was changed from the output of ''git diff somepath/somefile'' - it is always better to put things like &amp;quot;Bugfix - picked the wrong something for featureX&amp;quot; or &amp;quot;Updated image to reflect new pricing&amp;quot; to prevent someone else from having to stare at the diff output to work out what was changed.&lt;br /&gt;
&lt;br /&gt;
The 50 character limit is because some of the git commands use the first line of the log message and the output will look a bit messed up if it's too long. An example of this is ''git log --oneline''&lt;br /&gt;
&lt;br /&gt;
If you can't fit everything in about 50 characters or if the commit is particularly complicated, do not use the ''-m'' option with ''git commit''. You will be dropped into your editor of choice (most likely vi) and then can make the first line a 50 character summary of the commit, add a blank line and then any other comments that are required.&lt;br /&gt;
&lt;br /&gt;
== Configuration of git ==&lt;br /&gt;
&lt;br /&gt;
The following commands should all be run from the shell.&lt;br /&gt;
&lt;br /&gt;
 git config --global user.name &amp;quot;Simon Amor&amp;quot;&lt;br /&gt;
 git config --global user.email simon@leaky.org&lt;br /&gt;
 git config --global color.diff auto&lt;br /&gt;
 git config --global color.status auto&lt;br /&gt;
 git config --global color.branch auto&lt;br /&gt;
 git config --global diff.renamelimit 40960&lt;br /&gt;
&lt;br /&gt;
Recent versions of git will complain about the way git-push is going to work, to stop this it's recommended you use the following command. If you prefer the original behaviour for matching branches, use 'matching' instead of 'simple'&lt;br /&gt;
&lt;br /&gt;
 git config --global push.default simple&lt;br /&gt;
&lt;br /&gt;
* '''matching''' means git push will push all your local branches to the ones with the same name on the remote. This makes it easy to accidentally push a branch you didn't intend to.&lt;br /&gt;
* '''simple''' means git push will push only the current branch to the one that git pull would pull from, and also checks that their names match. This is a more intuitive behavior, which is why the default is getting changed to this.&lt;br /&gt;
&lt;br /&gt;
If you prefer long lines to be wrapped within less, the following will fix this.&lt;br /&gt;
&lt;br /&gt;
 git config --global core.pager 'less -+$LESS -iR'&lt;br /&gt;
&lt;br /&gt;
Other options you may with to add to -iR include -eFX (-e and -F are similar and relate to exiting on eof, -X doesn't initialise the terminal)&lt;br /&gt;
&lt;br /&gt;
== Showing all branches ==&lt;br /&gt;
&lt;br /&gt;
Because the repository is a clone of a remote repository, you need to specify -r to the ''git branch'' command to show remote branches as well.&lt;br /&gt;
&lt;br /&gt;
 git branch -r&lt;br /&gt;
&lt;br /&gt;
== Showing remote branches and local branches ==&lt;br /&gt;
&lt;br /&gt;
 git branch -a&lt;br /&gt;
&lt;br /&gt;
== Comparing branches ==&lt;br /&gt;
&lt;br /&gt;
git log has a number of options but the commonly used ones are:&lt;br /&gt;
* -p will include the patch for the commit&lt;br /&gt;
* --pretty=oneline returns just the sha1 and the first line of the commit message.&lt;br /&gt;
&lt;br /&gt;
To find all the commits that are in one or other branch, but not in both (exclude the common ancestors)&lt;br /&gt;
&lt;br /&gt;
 git log master...working&lt;br /&gt;
&lt;br /&gt;
This will show anything new that was added to ''master'' as well as anything new added to ''working''&lt;br /&gt;
&lt;br /&gt;
 git log master..working&lt;br /&gt;
&lt;br /&gt;
This will show anything new added to ''working'' that wasn't already in ''master''&lt;br /&gt;
&lt;br /&gt;
 git log working..master&lt;br /&gt;
&lt;br /&gt;
This will show anything new added to ''master'' that wasn't already in ''working''&lt;br /&gt;
&lt;br /&gt;
== View changes in Staged files ==&lt;br /&gt;
&lt;br /&gt;
Shows differences between HEAD and staged (added) file&lt;br /&gt;
&lt;br /&gt;
 git add myfile.txt&lt;br /&gt;
 git diff --cached myfile.txt&lt;br /&gt;
&lt;br /&gt;
== Merging a branch ==&lt;br /&gt;
&lt;br /&gt;
To merge branchname into the current branch, use ''git merge branchname'' - this will replay all the changes in the branch onto the current and hopefully not cause any conflicts.&lt;br /&gt;
&lt;br /&gt;
 git merge branchname&lt;br /&gt;
&lt;br /&gt;
== Rebasing a branch ==&lt;br /&gt;
&lt;br /&gt;
To go from something like this, where master has extra commits compared to a branch&lt;br /&gt;
&lt;br /&gt;
 * c32182bc - (HEAD -&amp;gt; master) Some minor cleanup from the broken code branch (3 minutes ago)&lt;br /&gt;
 | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago)&lt;br /&gt;
 | * 213ae299 - WIP #991/#993 (18 hours ago)&lt;br /&gt;
 | * c3c26b92 - WIP #991 - bulk editing (18 hours ago)&lt;br /&gt;
 |/&lt;br /&gt;
 * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago)&lt;br /&gt;
&lt;br /&gt;
to this where the branch has all the commits from master plus copies of it's own (the commit ids change in the process)&lt;br /&gt;
&lt;br /&gt;
 * 50de2cba - (HEAD -&amp;gt; broken-do-not-use-991-993) WIP #991/#993 - broken (19 seconds ago)&lt;br /&gt;
 * 8d3821db - WIP #991/#993 (3 minutes ago)&lt;br /&gt;
 * de390087 - WIP #991 - bulk editing (3 minutes ago)&lt;br /&gt;
 * c32182bc - (master) Some minor cleanup from the broken code branch (13 minutes ago)&lt;br /&gt;
 * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago)&lt;br /&gt;
&lt;br /&gt;
use the following command:&lt;br /&gt;
&lt;br /&gt;
 git rebase master broken-do-not-use-991-993&lt;br /&gt;
&lt;br /&gt;
Afterwards, you might want to switch back to the master branch as it'll leave you on the `broken-do-not-use-991-993` branch.&lt;br /&gt;
&lt;br /&gt;
== Deleting a merged branch ==&lt;br /&gt;
&lt;br /&gt;
Be very careful! To remove a branch from your local repository, simply use the following to list the branches&lt;br /&gt;
&lt;br /&gt;
 git branch&lt;br /&gt;
&lt;br /&gt;
and to remove the branch called ''branchname''&lt;br /&gt;
&lt;br /&gt;
 git branch -d branchname&lt;br /&gt;
&lt;br /&gt;
If it has not been merged into another branch, you might get a warning that it contains unmerged content.&lt;br /&gt;
&lt;br /&gt;
In order to remove the branch from your remote repository, you need to specifically push an empty repository to that branch.&lt;br /&gt;
&lt;br /&gt;
 git push origin :branchname&lt;br /&gt;
&lt;br /&gt;
Once it's removed from both your local and remote repositories, it most likely cannot be retrieved unless someone else fetched your remote repository and still has a copy of it!&lt;br /&gt;
&lt;br /&gt;
== Viewing a previous revision of a file ==&lt;br /&gt;
&lt;br /&gt;
To view the content of a previous revision of a file without checking out that revision, use '''git show'''&lt;br /&gt;
&lt;br /&gt;
 git show dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/mytestscript.pl&lt;br /&gt;
&lt;br /&gt;
You can also redirect the output to a file, for example if you want to revert an image rather than text.&lt;br /&gt;
&lt;br /&gt;
== Viewing the directory listing for a previous revision ==&lt;br /&gt;
&lt;br /&gt;
It may be the case that after a particular revision, some files have been removed but you want to know what files were present (maybe to use git show with them to view the content).&lt;br /&gt;
&lt;br /&gt;
To view the top-level directory of the repository&lt;br /&gt;
&lt;br /&gt;
 git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b&lt;br /&gt;
&lt;br /&gt;
To view the contents of a specific path&lt;br /&gt;
&lt;br /&gt;
 git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/somedir/&lt;br /&gt;
&lt;br /&gt;
The files listed can be viewed either using git show ''revision'':''path'' or git show ''blob-id'' where the blob id is the third column in the output from git ls-tree.&lt;br /&gt;
&lt;br /&gt;
== View creation dates of branches ==&lt;br /&gt;
&lt;br /&gt;
 git for-each-ref --sort='-authordate:iso8601' \&lt;br /&gt;
   --format=' %(authordate:iso8601)%09%(refname)' refs/heads&lt;br /&gt;
&lt;br /&gt;
== Add specific lines ==&lt;br /&gt;
&lt;br /&gt;
 git add -e filepath/filename&lt;br /&gt;
&lt;br /&gt;
This will open up the differences of the file into vi, remove all changes that you don't want applied to this patch then :wq to save and apply the new add.&lt;br /&gt;
To cancel the patch and not apply any changes delete all lines in vi and :wq&lt;br /&gt;
&lt;br /&gt;
An alternative to this, if the hunks you wish to commit are separate, is to use&lt;br /&gt;
&lt;br /&gt;
 git add -p filepath/filename&lt;br /&gt;
&lt;br /&gt;
This prompts you for each hunk whether to stage it (y), or skip it (n) - there are other options but generally these two are the only ones you'll need.&lt;br /&gt;
&lt;br /&gt;
== Fix half-updated dev box ==&lt;br /&gt;
&lt;br /&gt;
 git stash save&lt;br /&gt;
 git pull&lt;br /&gt;
 git stash apply &amp;lt;stashname&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Stash only specific files ==&lt;br /&gt;
&lt;br /&gt;
Stash usually stashes all changes, to stash only certain files, git add all the files that you don't want stashed, then run&lt;br /&gt;
&lt;br /&gt;
 git stash --keep-index&lt;br /&gt;
&lt;br /&gt;
== View log for a file that has since been deleted ==&lt;br /&gt;
&lt;br /&gt;
 git log -p --follow -- full/file/path.txt&lt;br /&gt;
&lt;br /&gt;
== Viewing the diff ignoring whitespace changes ==&lt;br /&gt;
&lt;br /&gt;
 git diff --ignore-space-at-eol -b -w simon/mytestscript.pl&lt;br /&gt;
&lt;br /&gt;
== Graphical view of commits ==&lt;br /&gt;
&lt;br /&gt;
A semi-graphical view of how the current branch has branched and merged.&lt;br /&gt;
&lt;br /&gt;
 git log --graph --oneline&lt;br /&gt;
&lt;br /&gt;
== Rewrite author of all commits ==&lt;br /&gt;
&lt;br /&gt;
Committed an entire repository with the wrong email/name for the committer? Run the following to reset everything. '''Be careful!'''&lt;br /&gt;
&lt;br /&gt;
 git filter-branch -f --env-filter \&lt;br /&gt;
  &amp;quot;GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \&lt;br /&gt;
  GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';&amp;quot; HEAD&lt;br /&gt;
&lt;br /&gt;
Output (for a repository with only 4 commits):&lt;br /&gt;
&lt;br /&gt;
 Rewrite e996a36094ba2a516dcf6bebc115f7ac25b2da6a (1/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 511aef3d14e92dbc2847934cf6313fd328aaf33d (2/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 0d6b36c9c27568161e4b4a47b2fdeefc98742379 (3/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 65b29f4418d773704e7055399c55959e45953108 (4/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Ref 'refs/heads/master' was rewritten&lt;br /&gt;
&lt;br /&gt;
== Storing the .git directory outside the work tree ==&lt;br /&gt;
&lt;br /&gt;
* content copied from http://stackoverflow.com/questions/505467/can-i-store-the-git-folder-outside-the-files-i-want-tracked&lt;br /&gt;
&lt;br /&gt;
You just need to ensure that the repository knows where the work tree is and vice versa.&lt;br /&gt;
&lt;br /&gt;
To let the repository know where the work tree is, set the configuration value core.worktree. To let the work tree know where it's git directory is, add a file named .git (not a folder!) and add a line like&lt;br /&gt;
&lt;br /&gt;
 gitdir: /path/to/repo.git&lt;br /&gt;
&lt;br /&gt;
Since git 1.7.5 the init command learned an extra option for this. You can initialize a new separate repository with&lt;br /&gt;
&lt;br /&gt;
 git --separate-git-dir /path/to/repo.git init&lt;br /&gt;
&lt;br /&gt;
This will initialize the git repository in the separate directory and add the .git file in the current directory, which is the working directory of the new repository. (Note: tried on 1.8.3 and it didn't recognise the option)&lt;br /&gt;
&lt;br /&gt;
Previously to 1.7.5 you had to use slightly different parameters and add the .git file yourself. To initialize a separate repository the following command links the work-tree with the repository:&lt;br /&gt;
&lt;br /&gt;
 git --git-dir=/path/to/repo.git --work-tree=. init &amp;amp;&amp;amp; echo &amp;quot;gitdir: /path/to/repo.git&amp;quot; &amp;gt; .git&lt;br /&gt;
&lt;br /&gt;
Your current directory will be the working tree and git will use the repository at /path/to/repo.git. The init command will automatically set the core.worktree value as specified with the --git-dir parameter.&lt;br /&gt;
&lt;br /&gt;
== Updating git ==&lt;br /&gt;
&lt;br /&gt;
To update CentOS7 to the latest version 2 git, use the IUS repository.&lt;br /&gt;
&lt;br /&gt;
Get the package url from https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/repoview/git2u.html and use it in the following command:&lt;br /&gt;
&lt;br /&gt;
 # yum install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/git2u-2.11.1-1.ius.centos7.x86_64.rpm&lt;br /&gt;
&lt;br /&gt;
If you already have the default version of git installed, you'll need to remove it first with this command:&lt;br /&gt;
&lt;br /&gt;
 # yum remove git perl-Git&lt;br /&gt;
&lt;br /&gt;
== Aliases ==&lt;br /&gt;
&lt;br /&gt;
Edit ~/.gitconfig and add:&lt;br /&gt;
&lt;br /&gt;
 [alias]&lt;br /&gt;
    lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset'&lt;br /&gt;
&lt;br /&gt;
or if you're the only author in this repository, you can skip the author name at the end and use this instead:&lt;br /&gt;
&lt;br /&gt;
    lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)'&lt;br /&gt;
&lt;br /&gt;
This will cause `git lg --all` to show this kind of graph with colours for various parts of the line such as a red hash, yellow branch name and green time.&lt;br /&gt;
&lt;br /&gt;
 * c32182bc - (HEAD -&amp;gt; master) Some minor cleanup from the broken code branch (3 minutes ago)&lt;br /&gt;
 | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago)&lt;br /&gt;
 | * 213ae299 - WIP #991/#993 (18 hours ago)&lt;br /&gt;
 | * c3c26b92 - WIP #991 - bulk editing (18 hours ago)&lt;br /&gt;
 |/&lt;br /&gt;
 * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago)&lt;br /&gt;
 * f3a6767e - Minor tidying up of code (18 hours ago)&lt;br /&gt;
 * 72955241 - Code cleanup, change FIXME to TODO (3 days ago)&lt;br /&gt;
 * 5a620f20 - Removed a lot of TODO (3 days ago)&lt;br /&gt;
 * 53ef9e74 - Fixes #987 - file viewer default directory/filename (3 days ago)&lt;br /&gt;
 *   b3f37ddd - (upstream/master) Merge pull request #997 from simonamor/master (2 weeks ago)&lt;br /&gt;
 |\&lt;br /&gt;
 | * 398167db - Fixes #517 - disable group if width=0 (2 weeks ago)&lt;br /&gt;
 | * a3f02ec5 - Handles bottom line (2 weeks ago)&lt;br /&gt;
 | * dc957aad - WIP #979 - most of the margins are handled during autoarranging now (4 months ago)&lt;br /&gt;
 | * 8d060bd6 - Updated all nuget packages and target to .NET Framework 4.8 (4 months ago)&lt;br /&gt;
 | * 622f3023 - Retarget everything to .NET Framework 4.8 (4 months ago)&lt;br /&gt;
 |/&lt;br /&gt;
 *   684fd55f - Merge pull request #974 from simonamor/master (7 months ago)&lt;br /&gt;
&lt;br /&gt;
Prevent accidental double (or more) git's from causing errors. e.g `git git status` =&amp;gt; `git status`&lt;br /&gt;
&lt;br /&gt;
 git config --global alias.git '!exec git'&lt;br /&gt;
&lt;br /&gt;
(or add this to your .gitconfig)&lt;br /&gt;
&lt;br /&gt;
 [alias]&lt;br /&gt;
   git = !exec git&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Git&amp;diff=397</id>
		<title>Git</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Git&amp;diff=397"/>
				<updated>2021-05-13T09:17:24Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Aliases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellpadding=10 align=right&lt;br /&gt;
| __TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Writing Good Commit Messages ==&lt;br /&gt;
&lt;br /&gt;
There are just two rules for writing good commit messages.&lt;br /&gt;
&lt;br /&gt;
# '''DO NOT''' just put &amp;quot;bugfix&amp;quot; or &amp;quot;updated this&amp;quot;&lt;br /&gt;
# '''Limit the commit message to approx 50 characters'''&lt;br /&gt;
&lt;br /&gt;
Unless it is immediately obvious what was changed from the output of ''git diff somepath/somefile'' - it is always better to put things like &amp;quot;Bugfix - picked the wrong something for featureX&amp;quot; or &amp;quot;Updated image to reflect new pricing&amp;quot; to prevent someone else from having to stare at the diff output to work out what was changed.&lt;br /&gt;
&lt;br /&gt;
The 50 character limit is because some of the git commands use the first line of the log message and the output will look a bit messed up if it's too long. An example of this is ''git log --oneline''&lt;br /&gt;
&lt;br /&gt;
If you can't fit everything in about 50 characters or if the commit is particularly complicated, do not use the ''-m'' option with ''git commit''. You will be dropped into your editor of choice (most likely vi) and then can make the first line a 50 character summary of the commit, add a blank line and then any other comments that are required.&lt;br /&gt;
&lt;br /&gt;
== Configuration of git ==&lt;br /&gt;
&lt;br /&gt;
The following commands should all be run from the shell.&lt;br /&gt;
&lt;br /&gt;
 git config --global user.name &amp;quot;Simon Amor&amp;quot;&lt;br /&gt;
 git config --global user.email simon@leaky.org&lt;br /&gt;
 git config --global color.diff auto&lt;br /&gt;
 git config --global color.status auto&lt;br /&gt;
 git config --global color.branch auto&lt;br /&gt;
 git config --global diff.renamelimit 40960&lt;br /&gt;
&lt;br /&gt;
Recent versions of git will complain about the way git-push is going to work, to stop this it's recommended you use the following command. If you prefer the original behaviour for matching branches, use 'matching' instead of 'simple'&lt;br /&gt;
&lt;br /&gt;
 git config --global push.default simple&lt;br /&gt;
&lt;br /&gt;
* '''matching''' means git push will push all your local branches to the ones with the same name on the remote. This makes it easy to accidentally push a branch you didn't intend to.&lt;br /&gt;
* '''simple''' means git push will push only the current branch to the one that git pull would pull from, and also checks that their names match. This is a more intuitive behavior, which is why the default is getting changed to this.&lt;br /&gt;
&lt;br /&gt;
If you prefer long lines to be wrapped within less, the following will fix this.&lt;br /&gt;
&lt;br /&gt;
 git config --global core.pager 'less -+$LESS -iR'&lt;br /&gt;
&lt;br /&gt;
Other options you may with to add to -iR include -eFX (-e and -F are similar and relate to exiting on eof, -X doesn't initialise the terminal)&lt;br /&gt;
&lt;br /&gt;
== Showing all branches ==&lt;br /&gt;
&lt;br /&gt;
Because the repository is a clone of a remote repository, you need to specify -r to the ''git branch'' command to show remote branches as well.&lt;br /&gt;
&lt;br /&gt;
 git branch -r&lt;br /&gt;
&lt;br /&gt;
== Showing remote branches and local branches ==&lt;br /&gt;
&lt;br /&gt;
 git branch -a&lt;br /&gt;
&lt;br /&gt;
== Comparing branches ==&lt;br /&gt;
&lt;br /&gt;
git log has a number of options but the commonly used ones are:&lt;br /&gt;
* -p will include the patch for the commit&lt;br /&gt;
* --pretty=oneline returns just the sha1 and the first line of the commit message.&lt;br /&gt;
&lt;br /&gt;
To find all the commits that are in one or other branch, but not in both (exclude the common ancestors)&lt;br /&gt;
&lt;br /&gt;
 git log master...working&lt;br /&gt;
&lt;br /&gt;
This will show anything new that was added to ''master'' as well as anything new added to ''working''&lt;br /&gt;
&lt;br /&gt;
 git log master..working&lt;br /&gt;
&lt;br /&gt;
This will show anything new added to ''working'' that wasn't already in ''master''&lt;br /&gt;
&lt;br /&gt;
 git log working..master&lt;br /&gt;
&lt;br /&gt;
This will show anything new added to ''master'' that wasn't already in ''working''&lt;br /&gt;
&lt;br /&gt;
== View changes in Staged files ==&lt;br /&gt;
&lt;br /&gt;
Shows differences between HEAD and staged (added) file&lt;br /&gt;
&lt;br /&gt;
 git add myfile.txt&lt;br /&gt;
 git diff --cached myfile.txt&lt;br /&gt;
&lt;br /&gt;
== Merging a branch ==&lt;br /&gt;
&lt;br /&gt;
To merge branchname into the current branch, use ''git merge branchname'' - this will replay all the changes in the branch onto the current and hopefully not cause any conflicts.&lt;br /&gt;
&lt;br /&gt;
 git merge branchname&lt;br /&gt;
&lt;br /&gt;
== Deleting a merged branch ==&lt;br /&gt;
&lt;br /&gt;
Be very careful! To remove a branch from your local repository, simply use the following to list the branches&lt;br /&gt;
&lt;br /&gt;
 git branch&lt;br /&gt;
&lt;br /&gt;
and to remove the branch called ''branchname''&lt;br /&gt;
&lt;br /&gt;
 git branch -d branchname&lt;br /&gt;
&lt;br /&gt;
If it has not been merged into another branch, you might get a warning that it contains unmerged content.&lt;br /&gt;
&lt;br /&gt;
In order to remove the branch from your remote repository, you need to specifically push an empty repository to that branch.&lt;br /&gt;
&lt;br /&gt;
 git push origin :branchname&lt;br /&gt;
&lt;br /&gt;
Once it's removed from both your local and remote repositories, it most likely cannot be retrieved unless someone else fetched your remote repository and still has a copy of it!&lt;br /&gt;
&lt;br /&gt;
== Viewing a previous revision of a file ==&lt;br /&gt;
&lt;br /&gt;
To view the content of a previous revision of a file without checking out that revision, use '''git show'''&lt;br /&gt;
&lt;br /&gt;
 git show dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/mytestscript.pl&lt;br /&gt;
&lt;br /&gt;
You can also redirect the output to a file, for example if you want to revert an image rather than text.&lt;br /&gt;
&lt;br /&gt;
== Viewing the directory listing for a previous revision ==&lt;br /&gt;
&lt;br /&gt;
It may be the case that after a particular revision, some files have been removed but you want to know what files were present (maybe to use git show with them to view the content).&lt;br /&gt;
&lt;br /&gt;
To view the top-level directory of the repository&lt;br /&gt;
&lt;br /&gt;
 git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b&lt;br /&gt;
&lt;br /&gt;
To view the contents of a specific path&lt;br /&gt;
&lt;br /&gt;
 git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/somedir/&lt;br /&gt;
&lt;br /&gt;
The files listed can be viewed either using git show ''revision'':''path'' or git show ''blob-id'' where the blob id is the third column in the output from git ls-tree.&lt;br /&gt;
&lt;br /&gt;
== View creation dates of branches ==&lt;br /&gt;
&lt;br /&gt;
 git for-each-ref --sort='-authordate:iso8601' \&lt;br /&gt;
   --format=' %(authordate:iso8601)%09%(refname)' refs/heads&lt;br /&gt;
&lt;br /&gt;
== Add specific lines ==&lt;br /&gt;
&lt;br /&gt;
 git add -e filepath/filename&lt;br /&gt;
&lt;br /&gt;
This will open up the differences of the file into vi, remove all changes that you don't want applied to this patch then :wq to save and apply the new add.&lt;br /&gt;
To cancel the patch and not apply any changes delete all lines in vi and :wq&lt;br /&gt;
&lt;br /&gt;
An alternative to this, if the hunks you wish to commit are separate, is to use&lt;br /&gt;
&lt;br /&gt;
 git add -p filepath/filename&lt;br /&gt;
&lt;br /&gt;
This prompts you for each hunk whether to stage it (y), or skip it (n) - there are other options but generally these two are the only ones you'll need.&lt;br /&gt;
&lt;br /&gt;
== Fix half-updated dev box ==&lt;br /&gt;
&lt;br /&gt;
 git stash save&lt;br /&gt;
 git pull&lt;br /&gt;
 git stash apply &amp;lt;stashname&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Stash only specific files ==&lt;br /&gt;
&lt;br /&gt;
Stash usually stashes all changes, to stash only certain files, git add all the files that you don't want stashed, then run&lt;br /&gt;
&lt;br /&gt;
 git stash --keep-index&lt;br /&gt;
&lt;br /&gt;
== View log for a file that has since been deleted ==&lt;br /&gt;
&lt;br /&gt;
 git log -p --follow -- full/file/path.txt&lt;br /&gt;
&lt;br /&gt;
== Viewing the diff ignoring whitespace changes ==&lt;br /&gt;
&lt;br /&gt;
 git diff --ignore-space-at-eol -b -w simon/mytestscript.pl&lt;br /&gt;
&lt;br /&gt;
== Graphical view of commits ==&lt;br /&gt;
&lt;br /&gt;
A semi-graphical view of how the current branch has branched and merged.&lt;br /&gt;
&lt;br /&gt;
 git log --graph --oneline&lt;br /&gt;
&lt;br /&gt;
== Rewrite author of all commits ==&lt;br /&gt;
&lt;br /&gt;
Committed an entire repository with the wrong email/name for the committer? Run the following to reset everything. '''Be careful!'''&lt;br /&gt;
&lt;br /&gt;
 git filter-branch -f --env-filter \&lt;br /&gt;
  &amp;quot;GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \&lt;br /&gt;
  GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';&amp;quot; HEAD&lt;br /&gt;
&lt;br /&gt;
Output (for a repository with only 4 commits):&lt;br /&gt;
&lt;br /&gt;
 Rewrite e996a36094ba2a516dcf6bebc115f7ac25b2da6a (1/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 511aef3d14e92dbc2847934cf6313fd328aaf33d (2/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 0d6b36c9c27568161e4b4a47b2fdeefc98742379 (3/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 65b29f4418d773704e7055399c55959e45953108 (4/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Ref 'refs/heads/master' was rewritten&lt;br /&gt;
&lt;br /&gt;
== Storing the .git directory outside the work tree ==&lt;br /&gt;
&lt;br /&gt;
* content copied from http://stackoverflow.com/questions/505467/can-i-store-the-git-folder-outside-the-files-i-want-tracked&lt;br /&gt;
&lt;br /&gt;
You just need to ensure that the repository knows where the work tree is and vice versa.&lt;br /&gt;
&lt;br /&gt;
To let the repository know where the work tree is, set the configuration value core.worktree. To let the work tree know where it's git directory is, add a file named .git (not a folder!) and add a line like&lt;br /&gt;
&lt;br /&gt;
 gitdir: /path/to/repo.git&lt;br /&gt;
&lt;br /&gt;
Since git 1.7.5 the init command learned an extra option for this. You can initialize a new separate repository with&lt;br /&gt;
&lt;br /&gt;
 git --separate-git-dir /path/to/repo.git init&lt;br /&gt;
&lt;br /&gt;
This will initialize the git repository in the separate directory and add the .git file in the current directory, which is the working directory of the new repository. (Note: tried on 1.8.3 and it didn't recognise the option)&lt;br /&gt;
&lt;br /&gt;
Previously to 1.7.5 you had to use slightly different parameters and add the .git file yourself. To initialize a separate repository the following command links the work-tree with the repository:&lt;br /&gt;
&lt;br /&gt;
 git --git-dir=/path/to/repo.git --work-tree=. init &amp;amp;&amp;amp; echo &amp;quot;gitdir: /path/to/repo.git&amp;quot; &amp;gt; .git&lt;br /&gt;
&lt;br /&gt;
Your current directory will be the working tree and git will use the repository at /path/to/repo.git. The init command will automatically set the core.worktree value as specified with the --git-dir parameter.&lt;br /&gt;
&lt;br /&gt;
== Updating git ==&lt;br /&gt;
&lt;br /&gt;
To update CentOS7 to the latest version 2 git, use the IUS repository.&lt;br /&gt;
&lt;br /&gt;
Get the package url from https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/repoview/git2u.html and use it in the following command:&lt;br /&gt;
&lt;br /&gt;
 # yum install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/git2u-2.11.1-1.ius.centos7.x86_64.rpm&lt;br /&gt;
&lt;br /&gt;
If you already have the default version of git installed, you'll need to remove it first with this command:&lt;br /&gt;
&lt;br /&gt;
 # yum remove git perl-Git&lt;br /&gt;
&lt;br /&gt;
== Aliases ==&lt;br /&gt;
&lt;br /&gt;
Edit ~/.gitconfig and add:&lt;br /&gt;
&lt;br /&gt;
 [alias]&lt;br /&gt;
    lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset'&lt;br /&gt;
&lt;br /&gt;
or if you're the only author in this repository, you can skip the author name at the end and use this instead:&lt;br /&gt;
&lt;br /&gt;
    lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)'&lt;br /&gt;
&lt;br /&gt;
This will cause `git lg --all` to show this kind of graph with colours for various parts of the line such as a red hash, yellow branch name and green time.&lt;br /&gt;
&lt;br /&gt;
 * c32182bc - (HEAD -&amp;gt; master) Some minor cleanup from the broken code branch (3 minutes ago)&lt;br /&gt;
 | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago)&lt;br /&gt;
 | * 213ae299 - WIP #991/#993 (18 hours ago)&lt;br /&gt;
 | * c3c26b92 - WIP #991 - bulk editing (18 hours ago)&lt;br /&gt;
 |/&lt;br /&gt;
 * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago)&lt;br /&gt;
 * f3a6767e - Minor tidying up of code (18 hours ago)&lt;br /&gt;
 * 72955241 - Code cleanup, change FIXME to TODO (3 days ago)&lt;br /&gt;
 * 5a620f20 - Removed a lot of TODO (3 days ago)&lt;br /&gt;
 * 53ef9e74 - Fixes #987 - file viewer default directory/filename (3 days ago)&lt;br /&gt;
 *   b3f37ddd - (upstream/master) Merge pull request #997 from simonamor/master (2 weeks ago)&lt;br /&gt;
 |\&lt;br /&gt;
 | * 398167db - Fixes #517 - disable group if width=0 (2 weeks ago)&lt;br /&gt;
 | * a3f02ec5 - Handles bottom line (2 weeks ago)&lt;br /&gt;
 | * dc957aad - WIP #979 - most of the margins are handled during autoarranging now (4 months ago)&lt;br /&gt;
 | * 8d060bd6 - Updated all nuget packages and target to .NET Framework 4.8 (4 months ago)&lt;br /&gt;
 | * 622f3023 - Retarget everything to .NET Framework 4.8 (4 months ago)&lt;br /&gt;
 |/&lt;br /&gt;
 *   684fd55f - Merge pull request #974 from simonamor/master (7 months ago)&lt;br /&gt;
&lt;br /&gt;
Prevent accidental double (or more) git's from causing errors. e.g `git git status` =&amp;gt; `git status`&lt;br /&gt;
&lt;br /&gt;
 git config --global alias.git '!exec git'&lt;br /&gt;
&lt;br /&gt;
(or add this to your .gitconfig)&lt;br /&gt;
&lt;br /&gt;
 [alias]&lt;br /&gt;
   git = !exec git&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Windows10&amp;diff=396</id>
		<title>Windows10</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Windows10&amp;diff=396"/>
				<updated>2021-04-25T11:20:42Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Enabling the Windows 10 lock screen image information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Enabling the Windows 10 lock screen image information ==&lt;br /&gt;
&lt;br /&gt;
Click on Start &amp;gt; Run and type '''control userpasswords2''' to open the user management dialog. Click on the Advanced tab and untick the checkbox at the bottom for ''Require users to press Ctrl-Alt-Delete''&lt;br /&gt;
&lt;br /&gt;
== Disable Bing search for everything ==&lt;br /&gt;
&lt;br /&gt;
In the registry:&lt;br /&gt;
&lt;br /&gt;
 Computer\HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Explorer\DisableSearchBoxSuggestions = 1&lt;br /&gt;
&lt;br /&gt;
Restart the Windows Explorer process (or logout and back in)&lt;br /&gt;
&lt;br /&gt;
== Remove the 3D Objects folder from Explorer ==&lt;br /&gt;
&lt;br /&gt;
Press WIN+R key and type regedit&lt;br /&gt;
&lt;br /&gt;
From both of the following locations:&lt;br /&gt;
&lt;br /&gt;
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace&lt;br /&gt;
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace&lt;br /&gt;
&lt;br /&gt;
Delete the path and contents called:&lt;br /&gt;
&lt;br /&gt;
 {0DB7E03F-FC29-4DC6-9020-FF41B59E513A}&lt;br /&gt;
&lt;br /&gt;
Close all your Explorer windows and re-open one. The 3D Objects folder should be gone.&lt;br /&gt;
&lt;br /&gt;
== Comparison of files or folders ==&lt;br /&gt;
&lt;br /&gt;
Install '''WinMerge''' from [http://winmerge.org/ winmerge.org] - it includes a shell extension to allow easy comparison of files or folders.&lt;br /&gt;
&lt;br /&gt;
== View image EXIF data ==&lt;br /&gt;
&lt;br /&gt;
Picture Information Extractor (PIE) - free download&lt;br /&gt;
&lt;br /&gt;
* [https://www.picmeta.com/download.htm picmeta.com]&lt;br /&gt;
&lt;br /&gt;
== Checksum files ==&lt;br /&gt;
&lt;br /&gt;
Works in Windows 7 and 8 too.&lt;br /&gt;
&lt;br /&gt;
 certutil -HashFile filename.zip MD5&lt;br /&gt;
 certutil -HashFile filename.zip SHA1&lt;br /&gt;
&lt;br /&gt;
== MacOS QuickLook for Windows ==&lt;br /&gt;
&lt;br /&gt;
It allows user peek into a file content in lightning speed by just pressing the Space key.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/QL-Win/QuickLook QuickLook for Windows]&lt;br /&gt;
&lt;br /&gt;
== Ditto - multi-buffer clipboard ==&lt;br /&gt;
&lt;br /&gt;
[https://ditto-cp.sourceforge.io/ Direct from SourceForge] or via the [https://www.microsoft.com/en-us/p/ditto-clipboard/9nblggh3zbjq Microsoft Store]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Postcodes&amp;diff=395</id>
		<title>Postcodes</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Postcodes&amp;diff=395"/>
				<updated>2020-10-16T09:21:30Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot;Postcode validation by regex:    if ($postcode =~ /^([A-PR-UWYZ][0-9][0-9]?|[A-PR-UWYZ][A-HK-Y][0-9][0-9]?|[A-PR-UWYZ][0-9][A-HJKPSTUW]|[A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY])...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Postcode validation by regex:&lt;br /&gt;
&lt;br /&gt;
  if ($postcode =~ /^([A-PR-UWYZ][0-9][0-9]?|[A-PR-UWYZ][A-HK-Y][0-9][0-9]?|[A-PR-UWYZ][0-9][A-HJKPSTUW]|[A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]) ?([0-9][ABD-HJLNP-UWXYZ]{2})$/i) {&lt;br /&gt;
    $postcode = uc(&amp;quot;$1 $2&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    # postcode invalid format&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
Latest ONS Postcode Directory download can be found here:&lt;br /&gt;
&lt;br /&gt;
* https://geoportal.statistics.gov.uk/search?collection=Dataset&amp;amp;sort=-created&amp;amp;tags=onspd&lt;br /&gt;
&lt;br /&gt;
Easy HTTP API to reference ONS data:&lt;br /&gt;
&lt;br /&gt;
* https://api.postcodes.io/postcode/$postcode&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Jq&amp;diff=394</id>
		<title>Jq</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Jq&amp;diff=394"/>
				<updated>2020-10-12T11:31:53Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot;A utility for parsing and processing JSON data.  Download from https://stedolan.github.io/jq/  == Recipes ==  Download https://api.guildwars2.com/v1/maps.json and extract the...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A utility for parsing and processing JSON data.&lt;br /&gt;
&lt;br /&gt;
Download from https://stedolan.github.io/jq/&lt;br /&gt;
&lt;br /&gt;
== Recipes ==&lt;br /&gt;
&lt;br /&gt;
Download https://api.guildwars2.com/v1/maps.json and extract the name/id of all public maps&lt;br /&gt;
&lt;br /&gt;
 jq '.maps | to_entries[] | select (.value.type == &amp;quot;Public&amp;quot;) | {name:.value.map_name, id:.key}' maps.json&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;to_entries&amp;lt;/code&amp;gt; converts a hash into an array of objects consisting of &amp;lt;code&amp;gt;{ key:..., value:... }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; filters the objects&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=LVM&amp;diff=393</id>
		<title>LVM</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=LVM&amp;diff=393"/>
				<updated>2020-08-11T20:59:29Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== rescan the scsi bus ==&lt;br /&gt;
&lt;br /&gt;
If you've added another virtual disk to a VM, it may not see it without a reboot. If that's not going to be convenient it may show up by rescanning the scsi bus.&lt;br /&gt;
&lt;br /&gt;
 # echo &amp;quot;- - -&amp;quot; &amp;gt; /sys/class/scsi_host/host0/scan&lt;br /&gt;
&lt;br /&gt;
It may not be host0 so check what's available. After this the new drive should show up.&lt;br /&gt;
&lt;br /&gt;
== Creating new volumes ==&lt;br /&gt;
&lt;br /&gt;
Assuming that &amp;lt;code&amp;gt;/dev/sdb&amp;lt;/code&amp;gt; is a new disk with a single full size partition &amp;lt;code&amp;gt;/dev/sdb1&amp;lt;/code&amp;gt;, the following will create a new volume group called &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; and a couple of logical volumes inside called &amp;lt;code&amp;gt;projects&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;backups&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # vgcreate data /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # lvcreate -n projects -L 20G data&lt;br /&gt;
 # lvcreate -n backups -l 100%FREE data&lt;br /&gt;
&lt;br /&gt;
== Extending a filesystem to include a new partition ==&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT: Check the partitions, do not just copy/paste below!'''&lt;br /&gt;
&lt;br /&gt;
Initialise the LVM metadata on the partition to add into the filesystem&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
&lt;br /&gt;
Add the partition to the volume group&lt;br /&gt;
&lt;br /&gt;
 # vgextend sys /dev/sdb1&lt;br /&gt;
   Volume group &amp;quot;sys&amp;quot; successfully extended&lt;br /&gt;
&lt;br /&gt;
Extend the relevant logical volume to include all of the newly added space&lt;br /&gt;
&lt;br /&gt;
 # lvextend -l +100%FREE /dev/sys/root&lt;br /&gt;
  Size of logical volume sys/root changed from 27.88 GiB (892 extents) to 47.84 GiB (1531 extents).&lt;br /&gt;
  Logical volume root successfully resized&lt;br /&gt;
&lt;br /&gt;
Resize the underlying filesystem to use the whole LVM device&lt;br /&gt;
&lt;br /&gt;
 # resize2fs /dev/sys/root&lt;br /&gt;
 resize2fs 1.41.12 (17-May-2010)&lt;br /&gt;
 Filesystem at /dev/sys/root is mounted on /; on-line resizing required&lt;br /&gt;
 old desc_blocks = 2, new_desc_blocks = 3&lt;br /&gt;
 Performing an on-line resize of /dev/sys/root to 12541952 (4k) blocks.&lt;br /&gt;
 The filesystem on /dev/sys/root is now 12541952 blocks long.&lt;br /&gt;
&lt;br /&gt;
== Mounting a filesystem from a Xen disk file that has LVM on it ==&lt;br /&gt;
&lt;br /&gt;
 # losetup /dev/loop7 xenguest1.xvda.img&lt;br /&gt;
 # kpartx -v -a xenguest1.xvda.img&lt;br /&gt;
&lt;br /&gt;
If the disk partitions were just normal ones, you would be able to mount them now as /dev/loop7p1 /dev/loop7p2 etc. If the filesystems are contained within an LVM volume group there are some extra steps.&lt;br /&gt;
&lt;br /&gt;
Scan physical volumes for LVM partitions&lt;br /&gt;
&lt;br /&gt;
 # pvscan&lt;br /&gt;
 PV /dev/mapper/loop7p2   VG vg_xenguest1  lvm2 [29.51 GiB / 0    free]&lt;br /&gt;
&lt;br /&gt;
Scan the partitions for volume groups&lt;br /&gt;
&lt;br /&gt;
 # vgscan&lt;br /&gt;
 Reading all physical volumes.  This may take a while...&lt;br /&gt;
 Found volume group &amp;quot;vg_xenguest1&amp;quot; using metadata type lvm2&lt;br /&gt;
&lt;br /&gt;
Scan for logical volumes. Any that are currently in use will show ACTIVE in the first column.&lt;br /&gt;
&lt;br /&gt;
 # lvscan&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_root' [28.54 GiB] inherit&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_swap' [992.00 MiB] inherit&lt;br /&gt;
&lt;br /&gt;
Since these are inactive, they can't be used as devices (yet).&lt;br /&gt;
&lt;br /&gt;
 # lvdisplay /dev/vg_xenguest1/lv_root&lt;br /&gt;
 ...&lt;br /&gt;
  LV Status              NOT available&lt;br /&gt;
  LV Size                28.54 GiB&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
First we need to set the volume group active, and then the logical volumes should work fine.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -ay vg_xenguest1&lt;br /&gt;
 2 logical volume(s) in volume group &amp;quot;vg_xenguest1&amp;quot; now active&lt;br /&gt;
&lt;br /&gt;
And now we can mount the root filesystem.&lt;br /&gt;
&lt;br /&gt;
 # mkdir /mnt/xenguest1&lt;br /&gt;
 # mount -t ext3 /dev/mapper/vg_xenguest1/lv_root /mnt/xenguest1&lt;br /&gt;
&lt;br /&gt;
When you're finished with it, use the following commands to make the volumes inactive, remove the partitions from the kernel partition map and then remove the loopback device.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -an vg_xenguest1 &lt;br /&gt;
 # kpartx -v -d /dev/loop7&lt;br /&gt;
 # losetup -d /dev/loop7&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=CentOS7&amp;diff=392</id>
		<title>CentOS7</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=CentOS7&amp;diff=392"/>
				<updated>2019-11-08T14:05:43Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Enable disk quota on ext4 */ added yum notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also [[Upstart]]&lt;br /&gt;
&lt;br /&gt;
== Change server hostname ==&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# hostnamectl status&lt;br /&gt;
 &lt;br /&gt;
   Static hostname: localhost.localdomain&lt;br /&gt;
         Icon name: computer-vm&lt;br /&gt;
           Chassis: vm&lt;br /&gt;
        Machine ID: 399b74f54385ee0d782648666a204c25&lt;br /&gt;
           Boot ID: 411893b81fee4fb0b865e1b18fd8dd6d&lt;br /&gt;
    Virtualization: kvm&lt;br /&gt;
  Operating System: CentOS Linux 7 (Core)&lt;br /&gt;
       CPE OS Name: cpe:/o:centos:centos:7&lt;br /&gt;
            Kernel: Linux 3.10.0-123.el7.x86_64&lt;br /&gt;
      Architecture: x86_64&lt;br /&gt;
&lt;br /&gt;
Set the hostname.&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# hostnamectl set-hostname centos7.internal&lt;br /&gt;
&lt;br /&gt;
Check the host name again (Close the session and open new session using putty or console)&lt;br /&gt;
&lt;br /&gt;
== CentOS7 kernel panic on some hardware ==&lt;br /&gt;
&lt;br /&gt;
If you can't even get the installer to work and it just causes a kernel panic on startup, check this link: http://centosfaq.org/centos/centos-72-kernel-panic/&lt;br /&gt;
&lt;br /&gt;
The relevant info is pasted below in case the page is removed in the future.&lt;br /&gt;
&lt;br /&gt;
During the startup of the installer, edit the options for the kernel to include:&lt;br /&gt;
&lt;br /&gt;
 initcall_blacklist=clocksource_done_booting&lt;br /&gt;
&lt;br /&gt;
If the machine is already installed and you're moving the disks to another system and get a kernel panic, it's possible to use an older rescue disk and&lt;br /&gt;
&lt;br /&gt;
Append the line&lt;br /&gt;
&lt;br /&gt;
 GRUB_CMDLINE_LINUX_DEFAULT=”initcall_blacklist=clocksource_done_booting”&lt;br /&gt;
&lt;br /&gt;
to /etc/default/grub, and run&lt;br /&gt;
&lt;br /&gt;
 # grub2-mkconfig &amp;gt; /boot/grub2/grub.cfg&lt;br /&gt;
&lt;br /&gt;
On reboot this should allow you to boot succesfully.&lt;br /&gt;
&lt;br /&gt;
== Enable firewall ==&lt;br /&gt;
&lt;br /&gt;
Start the firewall running and set it to auto-start on bootup&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# systemctl start firewalld&lt;br /&gt;
 [root@localhost ~]# systemctl enable firewalld&lt;br /&gt;
&lt;br /&gt;
Enable HTTP and HTTPS&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=http&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=https&lt;br /&gt;
&lt;br /&gt;
Add a custom port for SSH&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-port=22222/tcp&lt;br /&gt;
&lt;br /&gt;
Remove the original SSH service&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --remove-service=ssh&lt;br /&gt;
&lt;br /&gt;
Add a rule for access to a service on a specific local port from a specific source IP&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public \&lt;br /&gt;
     --add-rich-rule='rule family=&amp;quot;ipv4&amp;quot; source address=&amp;quot;1.2.3.0/24&amp;quot;&lt;br /&gt;
     port protocol=&amp;quot;tcp&amp;quot; port=&amp;quot;22222&amp;quot; accept'&lt;br /&gt;
&lt;br /&gt;
Block a single IP from all services (and yes, that's a real IP that was pounding on a WordPress login page)&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --add-rich-rule=&amp;quot;rule family='ipv4' source address='176.28.22.192' reject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Reload the firewall rules&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --reload&lt;br /&gt;
&lt;br /&gt;
Add port forwarding for port 22 to port 922 on the same machine&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --add-forward-port=port=22:proto=tcp:toport=922&lt;br /&gt;
&lt;br /&gt;
== Disable firewalld and use iptables ==&lt;br /&gt;
&lt;br /&gt;
(content taken from racktables.com in case it disappears)&lt;br /&gt;
&lt;br /&gt;
The first step is to stop and mask the firewalld service (i.e., the service you do not want to use):&lt;br /&gt;
&lt;br /&gt;
 $ systemctl stop firewalld&lt;br /&gt;
 $ systemctl mask firewalld&lt;br /&gt;
&lt;br /&gt;
Then, install the &amp;quot;iptables-services&amp;quot; package (if it is not already installed):&lt;br /&gt;
&lt;br /&gt;
 $ yum install iptables-services&lt;br /&gt;
&lt;br /&gt;
Enable the service to start at boot-time:&lt;br /&gt;
&lt;br /&gt;
 $ systemctl enable iptables&lt;br /&gt;
&lt;br /&gt;
If you are saving your rules in that /etc/sysconfig/iptables file, you will then need to run one of the following commands:&lt;br /&gt;
&lt;br /&gt;
 $ service iptables restart  # OR:&lt;br /&gt;
 $ systemctl restart iptables&lt;br /&gt;
&lt;br /&gt;
Next, check that the iptables service is &amp;quot;active&amp;quot; with:&lt;br /&gt;
&lt;br /&gt;
 $ systemctl status iptables&lt;br /&gt;
&lt;br /&gt;
You can query the systemd journal for a &amp;quot;log&amp;quot; of the changes you made to the iptables service with:&lt;br /&gt;
&lt;br /&gt;
 $ journalctl -f -u iptables.service&lt;br /&gt;
&lt;br /&gt;
== Enable disk quota on ext4 ==&lt;br /&gt;
&lt;br /&gt;
Add to /etc/fstab the following options on the line with the ext4 fs (eg /home):&lt;br /&gt;
&lt;br /&gt;
 usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0&lt;br /&gt;
&lt;br /&gt;
Then check quotas and enable them&lt;br /&gt;
&lt;br /&gt;
 # quotaoff -a&lt;br /&gt;
 # quotacheck -auvgm&lt;br /&gt;
 # quotaon -a&lt;br /&gt;
&lt;br /&gt;
To check the quotas&lt;br /&gt;
&lt;br /&gt;
 # repquota -auv&lt;br /&gt;
&lt;br /&gt;
== Fix an interrupted yum upgrade ==&lt;br /&gt;
&lt;br /&gt;
(notes copied from [https://www.thegeekdiary.com/centos-rhel-67-how-to-recover-an-interrupted-yum-package-installation/ www.thegeekdiary.com])&lt;br /&gt;
&lt;br /&gt;
Normally if something interrupts a yum upgrade there will be duplicate package warnings or dependencies that haven't been filled. To resolve the problems, it's possible to retry the transaction.&lt;br /&gt;
&lt;br /&gt;
 # yum history&lt;br /&gt;
 Loaded plugins: fastestmirror&lt;br /&gt;
 ID     | Command line             | Date and time    | Action(s)      | Altered&lt;br /&gt;
 -------------------------------------------------------------------------------&lt;br /&gt;
    152 | upgrade                  | 2019-11-02 11:52 | E, I, U        |   29 **&lt;br /&gt;
    151 | upgrade -y               | 2019-10-20 12:44 | O, U           |   10 EE&lt;br /&gt;
    150 | upgrade                  | 2019-10-11 08:21 | Update         |    6&lt;br /&gt;
&lt;br /&gt;
In this instance, the ** at the end of id 152 indicates that the transaction was interrupted.&lt;br /&gt;
&lt;br /&gt;
 &amp;gt; - The rpmdb was changed, outside yum, after the transaction.&lt;br /&gt;
 &amp;lt; - The rpmdb was changed, outside yum, before the transaction.&lt;br /&gt;
 * - The transaction aborted before completion.&lt;br /&gt;
 # - The transaction completed, but with a non-zero status.&lt;br /&gt;
 E - The transaction completed fine, but had warning/error output during the transaction.&lt;br /&gt;
 P - The transaction completed fine, but problems already existed in the rpmdb.&lt;br /&gt;
 s - The transaction completed fine, but --skip-broken was enabled and had to skip some packages.&lt;br /&gt;
&lt;br /&gt;
To resolve this issue, I force-reinstalled all the packages in transaction 152 using the '''redo force-reinstall''' option with yum history.&lt;br /&gt;
&lt;br /&gt;
 # yum history redo force-reinstall 152&lt;br /&gt;
&lt;br /&gt;
Always read what is going to be performed and don't blindly accept it otherwise the system may end up not working.&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Windows10&amp;diff=391</id>
		<title>Windows10</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Windows10&amp;diff=391"/>
				<updated>2019-11-02T14:26:02Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: added removal of 3d objects folder&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Enabling the Windows 10 lock screen image information ==&lt;br /&gt;
&lt;br /&gt;
Click on Start &amp;gt; Run and type '''control userpasswords2''' to open the user management dialog. Click on the Advanced tab and untick the checkbox at the bottom for ''Require users to press Ctrl-Alt-Delete''&lt;br /&gt;
&lt;br /&gt;
== Remove the 3D Objects folder from Explorer ==&lt;br /&gt;
&lt;br /&gt;
Press WIN+R key and type regedit&lt;br /&gt;
&lt;br /&gt;
From both of the following locations:&lt;br /&gt;
&lt;br /&gt;
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace&lt;br /&gt;
 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace&lt;br /&gt;
&lt;br /&gt;
Delete the path and contents called:&lt;br /&gt;
&lt;br /&gt;
 {0DB7E03F-FC29-4DC6-9020-FF41B59E513A}&lt;br /&gt;
&lt;br /&gt;
Close all your Explorer windows and re-open one. The 3D Objects folder should be gone.&lt;br /&gt;
&lt;br /&gt;
== Comparison of files or folders ==&lt;br /&gt;
&lt;br /&gt;
Install '''WinMerge''' from [http://winmerge.org/ winmerge.org] - it includes a shell extension to allow easy comparison of files or folders.&lt;br /&gt;
&lt;br /&gt;
== View image EXIF data ==&lt;br /&gt;
&lt;br /&gt;
Picture Information Extractor (PIE) - free download&lt;br /&gt;
&lt;br /&gt;
* [https://www.picmeta.com/download.htm picmeta.com]&lt;br /&gt;
&lt;br /&gt;
== Checksum files ==&lt;br /&gt;
&lt;br /&gt;
Works in Windows 7 and 8 too.&lt;br /&gt;
&lt;br /&gt;
 certutil -HashFile filename.zip MD5&lt;br /&gt;
 certutil -HashFile filename.zip SHA1&lt;br /&gt;
&lt;br /&gt;
== MacOS QuickLook for Windows ==&lt;br /&gt;
&lt;br /&gt;
It allows user peek into a file content in lightning speed by just pressing the Space key.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/QL-Win/QuickLook QuickLook for Windows]&lt;br /&gt;
&lt;br /&gt;
== Ditto - multi-buffer clipboard ==&lt;br /&gt;
&lt;br /&gt;
[https://ditto-cp.sourceforge.io/ Direct from SourceForge] or via the [https://www.microsoft.com/en-us/p/ditto-clipboard/9nblggh3zbjq Microsoft Store]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2019&amp;diff=390</id>
		<title>Books-2019</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2019&amp;diff=390"/>
				<updated>2019-10-02T09:10:40Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2018|Books from 2018]]&lt;br /&gt;
&lt;br /&gt;
== January 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Missing You (Harrington Bay Mysteries #2) - Vedam, Shereen&lt;br /&gt;
* Double Illusion - Shlian, Deborah&lt;br /&gt;
* A Vision A Day Keeps the Killer Away (Piper Ashwell Psychic P.I., #1) - Hashway, Kelly&lt;br /&gt;
&lt;br /&gt;
== February 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Death &amp;amp; Damages - Loofbourrow, Patricia&lt;br /&gt;
* Next Door (Chloe Fine Mystery #1) - Pierce, Blake&lt;br /&gt;
* The Hack (Hunter/O'Sullivan Adventure, #1) - Patching, Will&lt;br /&gt;
&lt;br /&gt;
== March 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Ghost Order (A Frank Bowen Conspiracy Thriller Book 3) - Tinsiano, Jay&lt;br /&gt;
* Convergence - Hicks, Michael Patrick&lt;br /&gt;
* Believe and Live: the horrific prelude to Broken Mirror - Sisco, Cody&lt;br /&gt;
* Past Tense (Jack Reacher, #23) - Child, Lee&lt;br /&gt;
&lt;br /&gt;
== April 2019 ==&lt;br /&gt;
&lt;br /&gt;
* The Gold Club: A White Collar Crime Thriller - Haskell, David&lt;br /&gt;
* Kill Switch (Angel of Darkness, #1) - Lee, Steve N.&lt;br /&gt;
* Neurotopia - Mohorovich, Tony&lt;br /&gt;
&lt;br /&gt;
== May 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Murder at Kensington Gardens - Strauss, Lee&lt;br /&gt;
* Dead Eye (Tiger's Eye Mystery, #1) - Day, Alyssa&lt;br /&gt;
* Menagerie - Tate, Kristy&lt;br /&gt;
* Shiftless (Wolf Rampant, #1) - Easterling, Aimee&lt;br /&gt;
* Half Wolf (Alpha Underground, #1) - Easterling, Aimee&lt;br /&gt;
* Huntress Born (Wolf Legacy, #1) - Easterling, Aimee&lt;br /&gt;
* Incendiary Magic (Dragon Mage Chronicles #2.5) - Easterling, Aimee&lt;br /&gt;
&lt;br /&gt;
== June 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Jaguar at the Portal - Easterling, Aimee&lt;br /&gt;
* The Right Man for Revenge (Jack Reacher Cases #2) - Ames, Dan&lt;br /&gt;
* A Man Made for Killing (Jack Reacher Cases #3) - Ames, Dan&lt;br /&gt;
* Dying for a Living (Dying for a Living, #1) - Shrum, Kory M.&lt;br /&gt;
* Dying by the Hour (Dying for a Living, #2) - Shrum, Kory M.&lt;br /&gt;
* Dying for Her (Dying for a Living, #3) - Shrum, Kory M.&lt;br /&gt;
&lt;br /&gt;
== July 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Dying Light (Dying for a Living, #4) - Shrum, Kory M.&lt;br /&gt;
* Worth Dying For (Dying for a Living, #5) - Shrum, Kory M.&lt;br /&gt;
* Dying Breath (Dying for a Living, #6) - Shrum, Kory M.&lt;br /&gt;
* Dying Day (Dying for a Living, #7) - Shrum, Kory M.&lt;br /&gt;
* It's a Little Haywire - Strauss, Elle&lt;br /&gt;
* Welcome To Lovely (The Lovely Mystery Series #1) - Clark, Candace&lt;br /&gt;
&lt;br /&gt;
== August 2019 ==&lt;br /&gt;
&lt;br /&gt;
* Am I the Killer? (A Luca Mystery #1) - Petrosini, Dan&lt;br /&gt;
* A Trace of Smoke (Hannah Vogel, #1) - Cantrell, Rebecca&lt;br /&gt;
* Two Percent Power: Delivering Justice (Two Percent Power #1) - Manning, Brian&lt;br /&gt;
* Kate Jones Thriller Series: Vol. 1: Bad Spirits, Dead of Winter, Death Rites, Touring for Death - Berkom, D.V.&lt;br /&gt;
* The Kate Jones Thriller Series, Vol. 2: (Cruising for Death, Yucatan Dead, A One Way Ticket to Dead) - Berkom, D.V.&lt;br /&gt;
&lt;br /&gt;
== September 2019 ==&lt;br /&gt;
&lt;br /&gt;
* The Emerald Buddha (Hansen Files, #4) - Dixon, Mike&lt;br /&gt;
* The Man With No Mercy (Jack Reacher Cases #5) - Ames, Dan&lt;br /&gt;
* A Man Out For Blood (Jack Reacher Cases #6) - Ames, Dan&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2018&amp;diff=389</id>
		<title>Books-2018</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2018&amp;diff=389"/>
				<updated>2019-10-02T09:05:42Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2017|Books from 2017]]&lt;br /&gt;
&lt;br /&gt;
Next page is [[Books-2019|Books from 2019]]&lt;br /&gt;
&lt;br /&gt;
== January 2018 ==&lt;br /&gt;
&lt;br /&gt;
Was reading an omnibus of 20+ books which was finished in February 2018&lt;br /&gt;
&lt;br /&gt;
== February 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Murder and Mayhem: A Limited Edition Thriller and Mystery Collection - Nathan M. Farrugia&lt;br /&gt;
&lt;br /&gt;
== March 2018 ==&lt;br /&gt;
&lt;br /&gt;
* The Eden Plague (Plague Wars, #0) - VanDyke, David&lt;br /&gt;
* Skull's Shadows (Plague Wars, #2) - VanDyke, David&lt;br /&gt;
* Eden's Exodus (Plague Wars, #3) - VanDyke, David&lt;br /&gt;
* The Austrian Asset (Justin Hall #10) - Jones, Ethan&lt;br /&gt;
* Dark Paradise (A Cooper &amp;amp; Quinn Mystery #4.5) - Lee, Catherine&lt;br /&gt;
* Harm None - North, Will&lt;br /&gt;
&lt;br /&gt;
== April 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Fatal Enemy (Jess Kimball Thriller #0.5) - Capri, Diane&lt;br /&gt;
* The Blasphemer (A Raines &amp;amp; Shaw Thriller #2) - Ling, John&lt;br /&gt;
* Driven to Death (Detective Bex Wynter Files, #1) - Harper, Elleby&lt;br /&gt;
* Interceptor (Helix #3) - Farrugia, Nathan M.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Exile (Helix #2) - Farrugia, Nathan M.&lt;br /&gt;
* Anomaly (Helix #4) - Farrugia, Nathan M.&lt;br /&gt;
* Inversion (Helix #5) - Farrugia, Nathan M.&lt;br /&gt;
* Exclave (Helix #6) - Farrugia, Nathan M.&lt;br /&gt;
* Diamonds and Cole (A Cole Sage Mystery, #1) - Maxwell, Micheal&lt;br /&gt;
&lt;br /&gt;
== May 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Critical Vulnerability: A Sasha McCandless Companion Novel (Aroostine Higgins, #1) - Miller, Melissa F.&lt;br /&gt;
* Hard Fall (A Thomas Blume Thriller, #1) - Reade, P.T.&lt;br /&gt;
* Snow Burn (A Thomas Blume Thriller, #2) - Reade, P.T.&lt;br /&gt;
* Situation Room (Luke Stone #3) - Mars, Jack&lt;br /&gt;
* Irreparable Harm (Sasha McCandless, #1) - Miller, Melissa F.&lt;br /&gt;
* Inadvertent Disclosure (Sasha McCandless, #2) - Miller, Melissa F.&lt;br /&gt;
* Irretrievably Broken (Sasha McCandless, #3) - Miller, Melissa F.&lt;br /&gt;
&lt;br /&gt;
== June 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Indispensable Party (Sasha McCandless, #4) - Miller, Melissa F.&lt;br /&gt;
* Lovers and Madmen (Sasha McCandless Novella, #4.5) - Miller, Melissa F.&lt;br /&gt;
* Improper Influence (Sasha McCandless, #5) - Miller, Melissa F.&lt;br /&gt;
* Dark Return (Leine Basso Thrillers, #6) - Berkom, D.V.&lt;br /&gt;
&lt;br /&gt;
== July 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Breaking Ground - A Tale of Mystery and Suspense Across Time - Campling, Mikey&lt;br /&gt;
* Flicker (Ember in Space, #1) - Rode, Rebecca&lt;br /&gt;
* Blood Orchids (Lei Crime, #1) - Neal, Toby&lt;br /&gt;
* Torch Ginger (Lei Crime, #2) - Neal, Toby&lt;br /&gt;
&lt;br /&gt;
== August 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Lion on Fire - Galdi, Ted&lt;br /&gt;
* In Sheep's Clothing (The Sydney Rye Mysteries #9) - Kimelman, Emily&lt;br /&gt;
&lt;br /&gt;
== September 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Playing with Matches (Playing with Matches #1) - Strauss, Lee&lt;br /&gt;
* The Last Man to Murder (Jack Reacher Cases #4) - Ames, Dan&lt;br /&gt;
* Transmission (The Invasion Chronicles, #1) - Rice, Morgan&lt;br /&gt;
* Crimson Snow: A Short Story - O'Flynn, Meghan&lt;br /&gt;
* Famished (Ash Park, #1) - O'Flynn, Meghan&lt;br /&gt;
&lt;br /&gt;
== October 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Sign Off (Caught Dead in Wyoming, #1) - McLinn, Patricia&lt;br /&gt;
* The Mockingbird Drive (Alex Vane #3) - Fuller, A.C.&lt;br /&gt;
* Incubation (The Incubation Trilogy, #1) - DiSilverio, Laura&lt;br /&gt;
* Incineration (The Incubation Trilogy Book 2) - DiSilverio, Laura&lt;br /&gt;
* Regeneration (The Incubation Trilogy Book 3) - DiSilverio, Laura&lt;br /&gt;
* A Hard Man to Forget (Jack Reacher Cases #1) - Ames, Dan&lt;br /&gt;
&lt;br /&gt;
== November 2018 ==&lt;br /&gt;
&lt;br /&gt;
* 48 Hours (City of London, #1) - Bentley, J. Jackson&lt;br /&gt;
* Suicide Forest (World's Scariest Places #1) - Bates, Jeremy&lt;br /&gt;
&lt;br /&gt;
== December 2018 ==&lt;br /&gt;
&lt;br /&gt;
* The Last Deception (Leine Basso Thrillers, #5) - Berkom, D.V.&lt;br /&gt;
* Brimstone and Ashes: The Extraordinary Adventures of the Good Witch Anaïs Blue Volume 3 (The Good Witch Anaïs Blue, #3) - Whittlesea, P.J.&lt;br /&gt;
* The Jacq of Spades (Red Dog Conspiracy, #1) - Loofbourrow, Patricia&lt;br /&gt;
* Vengeance (A Raines &amp;amp; Shaw Thriller #4) - Ling, John&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2019&amp;diff=388</id>
		<title>Books-2019</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2019&amp;diff=388"/>
				<updated>2019-10-01T11:20:15Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot; |__TOC__ |}  This page contains a list of boo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2018|Books from 2018]]&lt;br /&gt;
&lt;br /&gt;
== January 2019 ==&lt;br /&gt;
&lt;br /&gt;
== February 2019 ==&lt;br /&gt;
&lt;br /&gt;
== March 2019 ==&lt;br /&gt;
&lt;br /&gt;
== April 2019 ==&lt;br /&gt;
&lt;br /&gt;
== May 2019 ==&lt;br /&gt;
&lt;br /&gt;
== June 2019 ==&lt;br /&gt;
&lt;br /&gt;
== July 2019 ==&lt;br /&gt;
&lt;br /&gt;
== August 2019 ==&lt;br /&gt;
&lt;br /&gt;
== September 2019 ==&lt;br /&gt;
&lt;br /&gt;
== October 2019 ==&lt;br /&gt;
&lt;br /&gt;
== November 2019 ==&lt;br /&gt;
&lt;br /&gt;
== December 2019 ==&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2018&amp;diff=387</id>
		<title>Books-2018</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2018&amp;diff=387"/>
				<updated>2019-10-01T11:19:23Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot; |__TOC__ |}  This page contains a list of boo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2017|Books from 2017]]&lt;br /&gt;
&lt;br /&gt;
Next page is [[Books-2019|Books from 2019]]&lt;br /&gt;
&lt;br /&gt;
== January 2018 ==&lt;br /&gt;
&lt;br /&gt;
Was reading an omnibus of 20+ books which was finished in February 2018&lt;br /&gt;
&lt;br /&gt;
== February 2018 ==&lt;br /&gt;
&lt;br /&gt;
* Murder and Mayhem: A Limited Edition Thriller and Mystery Collection - Nathan M. Farrugia&lt;br /&gt;
&lt;br /&gt;
== March 2018 ==&lt;br /&gt;
&lt;br /&gt;
== April 2018 ==&lt;br /&gt;
&lt;br /&gt;
== May 2018 ==&lt;br /&gt;
&lt;br /&gt;
== June 2018 ==&lt;br /&gt;
&lt;br /&gt;
== July 2018 ==&lt;br /&gt;
&lt;br /&gt;
== August 2018 ==&lt;br /&gt;
&lt;br /&gt;
== September 2018 ==&lt;br /&gt;
&lt;br /&gt;
== October 2018 ==&lt;br /&gt;
&lt;br /&gt;
== November 2018 ==&lt;br /&gt;
&lt;br /&gt;
== December 2018 ==&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books&amp;diff=386</id>
		<title>Books</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books&amp;diff=386"/>
				<updated>2019-10-01T10:07:40Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series. &lt;br /&gt;
&lt;br /&gt;
== Books from 2013 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2013|a separate page for 2013]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2014 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2014|a separate page for 2014]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2015 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2015|a separate page for 2015]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2016 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2016|a separate page for 2016]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2017 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2017|a separate page for 2017]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2018 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2018|a separate page for 2018]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2019 ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-2019|a separate page for 2019]].&lt;br /&gt;
&lt;br /&gt;
== Books to read in the future ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Books-future|a separate page for the future]].&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2017&amp;diff=385</id>
		<title>Books-2017</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2017&amp;diff=385"/>
				<updated>2019-10-01T09:58:35Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2016|Books from 2016]]&lt;br /&gt;
&lt;br /&gt;
Next page is [[Books-2018|Books from 2018]]&lt;br /&gt;
&lt;br /&gt;
== January 2017 ==&lt;br /&gt;
&lt;br /&gt;
* Dead Wrong (Cal Murphy #7) - Patterson, Jack&lt;br /&gt;
* The Newcomer: Twelve Scifi Short Stories - Shaw, Alasdair C.&lt;br /&gt;
* Fifteen Minutes to Live - Sutton, Phoef&lt;br /&gt;
&lt;br /&gt;
== February 2017 ==&lt;br /&gt;
&lt;br /&gt;
* Psychic Visions Box Set 1-3 - Mayer, Dale&lt;br /&gt;
* Worm (Parahumans, #1) - Wildbow&lt;br /&gt;
* Vampire Girl (Vampire Girl, #1) - Kinrade, Karpov&lt;br /&gt;
* The Grave Man (Sam Prichard #1) - Archer, David&lt;br /&gt;
* Nightblade (Nightblade Epic #1) - Robinson, Garrett&lt;br /&gt;
&lt;br /&gt;
== March 2017 ==&lt;br /&gt;
&lt;br /&gt;
* Island of Fog (Island of Fog, #1) - Robinson, Keith&lt;br /&gt;
* Mystic (Nightblade Epic #2) - Robinson, Garrett&lt;br /&gt;
&lt;br /&gt;
== April 2017 ==&lt;br /&gt;
&lt;br /&gt;
* Yesterday's Gone: Season One - Platt, Sean&lt;br /&gt;
* Yesterday's Gone: Season Two - Platt, Sean&lt;br /&gt;
* The Medium (Emily Chambers Spirit Medium #1) - Archer, C.J.&lt;br /&gt;
* Death By Honeymoon (Caribbean Murder, #1) - Skye, Jaden&lt;br /&gt;
* Richter: A First Superhero Story (The First Superhero, #2.5) - Rutherford, Logan&lt;br /&gt;
* Monsters - Platt, Sean&lt;br /&gt;
* The First Lie (The Secrets of Selkie Moon, #1) - King, Virginia&lt;br /&gt;
* Entangled (Spellbound, #1) - Jefford, Nikki&lt;br /&gt;
&lt;br /&gt;
== May 2017 ==&lt;br /&gt;
&lt;br /&gt;
* The Foundation (Jack Emery #1) - Vincent, Steve P.&lt;br /&gt;
* Bad Traffick (Leine Basso Thrillers, #2) - Berkom, D.V.&lt;br /&gt;
* Alien Hunters (Alien Hunters, #1) - Arenson, Daniel&lt;br /&gt;
* Murder on the SS Rosa (Ginger Gold Mysteries #1) - Strauss, Lee&lt;br /&gt;
* Blood Ties (PI Julie Collins, #1) - Armstrong, Lori G.&lt;br /&gt;
* Deception (The Transformed, #1) - Claflin, Stacy&lt;br /&gt;
* Once Gone (Riley Paige Mystery, #1) - Pierce, Blake&lt;br /&gt;
* Once Taken (Riley Paige Mystery #2) - Pierce, Blake&lt;br /&gt;
* Moth (The Moth Saga #1) - Arenson, Daniel&lt;br /&gt;
&lt;br /&gt;
== June 2017 ==&lt;br /&gt;
&lt;br /&gt;
* The Mod Code (The Mod Code Series, #1) - Tankersley, Heidi&lt;br /&gt;
* The Island, A Mod Code Prequel Novella (The Mod Code Series, #0.5) - Tankersley, Heidi&lt;br /&gt;
* Cruel Justice (Lorne Simpkins, #1) - Comley, M.A.&lt;br /&gt;
* Impeding Justice (Lorne Simpkins, #2) - Comley, M.A.&lt;br /&gt;
* Murder at Hartigan House (Ginger Gold Mysteries #2) - Strauss, Lee&lt;br /&gt;
* Sharp Shooter (Tara Sharp, #1) - Delacourt, Marianne&lt;br /&gt;
* Fame is a Killer (Hope Hadley #1) - Potts, Meredith&lt;br /&gt;
* Loose Ends (California Corwin P.I. #1) - VanDyke, D.D.&lt;br /&gt;
* Off the Leash (California Corwin P.I., #2.5) - VanDyke, D.D.&lt;br /&gt;
* Complicated Blue: The Extraordinary Adventure of the Good Witch Anaïs Blue (The Good Witch Anaïs Blue, #1) - Whittlesea, P.J.&lt;br /&gt;
&lt;br /&gt;
== July 2017 ==&lt;br /&gt;
&lt;br /&gt;
* The Warren Omissions (James Flynn #1) - Patterson, Jack&lt;br /&gt;
* Good Investigations - Westerham, Ben&lt;br /&gt;
* In a Bind (California Corwin P.I. #2) - VanDyke, D.D.&lt;br /&gt;
* Reaper's Run (Plague Wars, #1) - VanDyke, David&lt;br /&gt;
* Keeper vs. Reaper (Graveyard Guardians, #1) - Wright, Jennifer Malone&lt;br /&gt;
* Rope Enough (The Romney and Marsh Files #1) - Tidy, Oliver&lt;br /&gt;
* The Promptuary (The Good Witch Anaïs Blue #2) - Whittlesea, P.J.&lt;br /&gt;
&lt;br /&gt;
== August 2017 ==&lt;br /&gt;
&lt;br /&gt;
* Too Good to Die: A David Good Private Investigator novel - Westerham, Ben&lt;br /&gt;
* Hunting Delilah - Baines, Anne&lt;br /&gt;
* Bullet Rain (Holly Lin #2; Nova Bartkowski) - Swartwood, Robert&lt;br /&gt;
* False Flag (Frank Bowen Conspiracy Thriller #1) - Tinsiano, Jay&lt;br /&gt;
* Slipknot (California Corwin P.I. #3) - VanDyke, D.D.&lt;br /&gt;
* Licensed to Thrill: Volume 1 (Hunt For Reacher #1-1.2) - Capri, Diane&lt;br /&gt;
&lt;br /&gt;
== September 2017 ==&lt;br /&gt;
&lt;br /&gt;
* Jack in the Green (Hunt for Reacher #2.5) - Capri, Diane&lt;br /&gt;
* Wired In (Paradise Crime, #1) - Neal, Toby&lt;br /&gt;
&lt;br /&gt;
== October 2017 ==&lt;br /&gt;
&lt;br /&gt;
* The Last Firewall (Singularity #3) - Hertling, William&lt;br /&gt;
* A Killing Truth (Leine Basso Thrillers, #0.5) - Berkom, D.V.&lt;br /&gt;
* The City of Shades (The Good Witch Anaïs Blue #0.5) - Whittlesea, P.J.&lt;br /&gt;
&lt;br /&gt;
== November 2017 ==&lt;br /&gt;
&lt;br /&gt;
Was reading an omnibus of 20+ books which was finished in 2018&lt;br /&gt;
&lt;br /&gt;
== December 2017 ==&lt;br /&gt;
&lt;br /&gt;
Was still reading an omnibus of 20+ books which was finished in 2018&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2016&amp;diff=384</id>
		<title>Books-2016</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2016&amp;diff=384"/>
				<updated>2019-10-01T09:39:37Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Created page with &amp;quot;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot; |__TOC__ |}  This page contains a list of boo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2015|Books from 2015]]&lt;br /&gt;
&lt;br /&gt;
Next page is [[Books-2017|Books from 2017]]&lt;br /&gt;
&lt;br /&gt;
== January 2016 ==&lt;br /&gt;
&lt;br /&gt;
* The Tesla Secret (The Project, #5) - Alex Lukeman&lt;br /&gt;
* Fresh Doubt (Ingrid Skyberg FBI Thriller #2) - Eva Hudson&lt;br /&gt;
* Run Girl - Eva Hudson&lt;br /&gt;
* Sea to Sky - A Hunter Rayne Highway Mystery #3) - R.E. Donald&lt;br /&gt;
* Family Magic (Hayle Coven #1) - Patti Larsen&lt;br /&gt;
* Shadow Sight (Ivy Granger #1) - E.J. Stevens&lt;br /&gt;
* Murder to Go (Food Truck Mysteries #1) - Chloe Kendrick&lt;br /&gt;
&lt;br /&gt;
== February 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Nightwalker (Stormwalker, #4) - Allyson James&lt;br /&gt;
* The Bionics (Bionics, #1) - Alicia Michaels&lt;br /&gt;
&lt;br /&gt;
== March 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Reckless Magic (Star-Crossed, #1) - Rachel Higginson&lt;br /&gt;
* Arctic Wargame (Justin Hall, #1) - Ethan Jones&lt;br /&gt;
* Priority Target (Carrie Chronicles #1) - Ethan Jones&lt;br /&gt;
* Tripoli's Target (Justin Hall, #2) - Ethan Jones&lt;br /&gt;
* An Eye for Murder (Ellie Foreman, #1) - Libby Fischer Hellmann&lt;br /&gt;
* Fog of War (Justin Hall, #3) - Ethan Jones&lt;br /&gt;
&lt;br /&gt;
== April 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Ops Files (Jet, #0.5) - Russell Blake&lt;br /&gt;
* Blood and Justice (Jake and Annie Lincoln, #1) - Rayven T. Hill&lt;br /&gt;
* Perception (The Perception Trilogy, #1) - Lee Strauss&lt;br /&gt;
* Any Means Necessary (Luke Stone #1) - Jack Mars&lt;br /&gt;
* Ambition (The Perception Trilogy, #0.5) - Lee Strauss&lt;br /&gt;
* Codename: Makarov (Carrie Chronicles #2) - Ethan Jones&lt;br /&gt;
* Drained (Agent Hank Rawlings, #1) - E.H. Reinhard&lt;br /&gt;
* Double Agents (Justin Hall, #4) - Ethan Jones&lt;br /&gt;
&lt;br /&gt;
== May 2016 ==&lt;br /&gt;
&lt;br /&gt;
* The Diplomat (Justin Hall, #4.5) - Jones, Ethan&lt;br /&gt;
* All Good Deeds (Lucy Kendall, #1) - Green, Stacy&lt;br /&gt;
* The Taste of Fear - Bates, Jeremy&lt;br /&gt;
&lt;br /&gt;
== June 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Helix (Helix #1) - Farrugia, Nathan M.&lt;br /&gt;
* Spell Found (Blackmoore Sisters Mystery, #7) - Dobbs, Leighann&lt;br /&gt;
* The Breakers Series: Books 1-3 (Breakers, #1-3) - Robertson, Edward W.&lt;br /&gt;
&lt;br /&gt;
== July 2016 ==&lt;br /&gt;
&lt;br /&gt;
== August 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Sundown on Top of the World (A Hunter Rayne Highway Mystery, #4) - Donald, R.E.&lt;br /&gt;
* Environmentally Friendly - Zanbaka, Elias&lt;br /&gt;
* Gone Bad (Jon Reznick, #3.5) - Turner, J.B.&lt;br /&gt;
* Dark Waters (Deborah Jones Crime Thriller, #2) - Turner, J.B.&lt;br /&gt;
&lt;br /&gt;
== September 2016 ==&lt;br /&gt;
&lt;br /&gt;
* The In-Betweener (Between Life and Death #1) - Christy, Ann&lt;br /&gt;
* Malevolent (Shaye Archer #1) - Deleon, Jana&lt;br /&gt;
* A Cutthroat Business (A Savannah Martin Mystery, #1) - Bennett, Jenna&lt;br /&gt;
* Hot Property (A Savannah Martin Mystery, #2) - Bennett, Jenna&lt;br /&gt;
* Contract Pending (A Savannah Martin Mystery, #3) - Bennett, Jenna&lt;br /&gt;
* Close to Home (A Savannah Martin Mystery, #4) - Bennett, Jenna&lt;br /&gt;
* Noble Beginnings (Jack Noble #1) - Ryan, L.T.&lt;br /&gt;
&lt;br /&gt;
== October 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Ignited (Ignited, #1) - Dantone, Desni&lt;br /&gt;
* Gingerbread Man (Nursery Rhyme Suspense #1) - Strauss, Lee&lt;br /&gt;
* Life is But a Dream (A Nursery Rhyme Suspense #2) - Strauss, Lee&lt;br /&gt;
* Blackmoore Sisters Cozy Mysteries Box-Set (Blackmoore Sisters Mystery #1-3) - Dobbs, Leighann&lt;br /&gt;
* See Them Run (Lucy Kendall, #2) - Green, Stacy&lt;br /&gt;
&lt;br /&gt;
== November 2016 ==&lt;br /&gt;
&lt;br /&gt;
* The Coalition - Marquis, Samuel&lt;br /&gt;
* Remorseless (Doc Powers &amp;amp; D.I. Carver Investigate, #1) - Patching, Will&lt;br /&gt;
* Make Me (Jack Reacher, #20) - Child, Lee&lt;br /&gt;
* Night School (Jack Reacher #21) - Child, Lee&lt;br /&gt;
&lt;br /&gt;
== December 2016 ==&lt;br /&gt;
&lt;br /&gt;
* Forever Road (Peri Jean Mace, #1) - Rhodes, Catie&lt;br /&gt;
* Against The Odds (Anna Dawson's Vegas, #1) - Jacobs, Mara&lt;br /&gt;
* Different (Tainted Elements, #1) - Linwood, Alycia&lt;br /&gt;
* Manhunt (Paul Richter, #6) - Barrington, James&lt;br /&gt;
* Overkill (Paul Richter, #1) - Barrington, James&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2015&amp;diff=383</id>
		<title>Books-2015</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2015&amp;diff=383"/>
				<updated>2019-10-01T08:55:44Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2014|Books from 2014]]&lt;br /&gt;
&lt;br /&gt;
Next page is [[Books-2016|Books from 2016]]&lt;br /&gt;
&lt;br /&gt;
== January 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Wanted - Nick Stephenson (Leopold Blake series)&lt;br /&gt;
* Ethan Justice: Origins - Simon Jenner&lt;br /&gt;
* The Killing League - Dani Amore&lt;br /&gt;
* Working for Bigfoot - Jim Butcher&lt;br /&gt;
* The Socket Greeny Saga book 1, Discovery - Tony Bertauski&lt;br /&gt;
* The Socket Greeny Saga book 2, Training - Tony Bertauski&lt;br /&gt;
* The Socket Greeny Saga book 3, Legend - Tony Bertauski&lt;br /&gt;
&lt;br /&gt;
* Tricknomancy - Michael A. Stackpole&lt;br /&gt;
&lt;br /&gt;
== February 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Multiple Motives - Kassandra Lamb&lt;br /&gt;
* Back on Murder (A Roland March Mystery, #1) - J. Mark Bertrand&lt;br /&gt;
* Due Justice - Diane Capri&lt;br /&gt;
&lt;br /&gt;
== March 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Fatal Distraction - Diane Capri&lt;br /&gt;
* Project ELE - Rebecca Gober &amp;amp; Courtney Nuckels&lt;br /&gt;
* Florida is murder - Diane Capri &amp;amp; Christine Kling&lt;br /&gt;
&lt;br /&gt;
== April 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Talented (book 1) - Sophie Davis&lt;br /&gt;
* Caged (book 2) - Sophie Davis&lt;br /&gt;
* Hunted (book 3) - Sophie Davis&lt;br /&gt;
&lt;br /&gt;
* Created (book 4) - Sophie Davis&lt;br /&gt;
&lt;br /&gt;
== May 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Twisted Justice - Diane Capri&lt;br /&gt;
* Working Stiff - Kevin J. Anderson&lt;br /&gt;
* Leave No Stone Unturned (Lexie Starr #1) - Jeanne Glidewell&lt;br /&gt;
* The Extinguished Guest (Lexie Starr #2) - Jeanne Glidewell&lt;br /&gt;
* Haunted (Lexie Starr #3) - Jeanne Glidewell&lt;br /&gt;
* Red Notice - Andy McNab&lt;br /&gt;
&lt;br /&gt;
== June 2015 ==&lt;br /&gt;
&lt;br /&gt;
* The Tesla Legacy - Rebecca Cantrell&lt;br /&gt;
* Rush - Eve Silver&lt;br /&gt;
* Don't Know Jack - Diane Capri (Hunt for Jack Reacher series #1)&lt;br /&gt;
* Edgewood - Karen McQuestion&lt;br /&gt;
* Omega Dog - Tim Stevens&lt;br /&gt;
* Unforeseen (Thomas Prescott #1) - Nick Pirog&lt;br /&gt;
* Trust - Pamela M. Kelley&lt;br /&gt;
&lt;br /&gt;
== July 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Slow curve on the Coquihalla - RE Donald&lt;br /&gt;
* The Forgotten Girls (Suburban Murder #1) - Alexa Steele&lt;br /&gt;
* Personal (Jack Reacher #19) - Lee Child&lt;br /&gt;
* Skin Game (Harry Dresden #15) - Jim Butcher&lt;br /&gt;
* Dance with the enemy - Rob Sinclair&lt;br /&gt;
&lt;br /&gt;
== August 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Cabal - Clive Barker&lt;br /&gt;
* Truth lies bleeding - Tony Black&lt;br /&gt;
* Misadventures of the Laundry Hag: Skeletons in the closet - Jennifer L. Hart&lt;br /&gt;
* Dream series - Dream Student - J.J. DiBenedetto&lt;br /&gt;
* Dead Line - Jack Patterson&lt;br /&gt;
* The Reordering- Vicki Pettersson&lt;br /&gt;
&lt;br /&gt;
== September 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Carmodys Run - Bill Pronzini&lt;br /&gt;
* Crimson Son - Russ Linton&lt;br /&gt;
* Uglies - Scott Westerfeld&lt;br /&gt;
* Ice on the Grapevine - RE Donald&lt;br /&gt;
&lt;br /&gt;
== October 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Becoming Alpha (Alpha Girl #1) - Aileen Erin&lt;br /&gt;
* Avoiding Alpha (Alpha Girl #2) - Aileen Erin&lt;br /&gt;
* Alpha Divided (Alpha Girl #3) - Aileen Erin&lt;br /&gt;
* Bruja (Alpha Girl #4) - Aileen Erin&lt;br /&gt;
* Alpha Unleashed (Alpha Girl #5) - Aileen Erin&lt;br /&gt;
* Dead in the Water (Cal Murphy #5) - Jack Patterson&lt;br /&gt;
&lt;br /&gt;
== November 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Jack in a Box - Diane Capri (Hunt for Jack Reacher #2)&lt;br /&gt;
* Jack and Kill - Diane Capri (Hunt for Jack Reacher #3)&lt;br /&gt;
* Get Back Jack - Diane Capri (Hunt for Jack Reacher #4)&lt;br /&gt;
* Hooked, A Thriller - Ruth Harris&lt;br /&gt;
* Blood and Snow omnibus edition - RaShelle Workman&lt;br /&gt;
** Blood and Snow BOOK 1&lt;br /&gt;
** Blood and Snow BOOK 2&lt;br /&gt;
** Blood and Snow BOOK 3&lt;br /&gt;
** Cindy Witch&lt;br /&gt;
** The Hunter's Tale&lt;br /&gt;
** Gabriel&lt;br /&gt;
** After The Kiss&lt;br /&gt;
&lt;br /&gt;
== December 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Blood and Snow omnibus edition - RaShelle Workman&lt;br /&gt;
** Blood and Snow BOOK 4: The Cindy Chronicles&lt;br /&gt;
** Blood and Snow BOOK 5: Vampire Lies&lt;br /&gt;
** Blood and Snow BOOK 6: A Beauty So Beastly&lt;br /&gt;
** Blood and Snow BOOK 7: Vampire Secrets&lt;br /&gt;
** Blood and Snow BOOK 8: Asha Ever After&lt;br /&gt;
** Blood and Snow BOOK 9: Vampire Nights&lt;br /&gt;
** The Professor's Origin&lt;br /&gt;
** Blood and Snow BOOK 10.1: The Dark Moth Society, Alice&lt;br /&gt;
* Played to Death (Scott Drayco #1) - BV Lawson&lt;br /&gt;
* Gypsy Hunted - Andrea Drew&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books&amp;diff=382</id>
		<title>Books</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books&amp;diff=382"/>
				<updated>2019-10-01T08:53:49Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series. &lt;br /&gt;
&lt;br /&gt;
== Books from 2013 ==&lt;br /&gt;
&lt;br /&gt;
Now moved to [[Books-2013|a separate page for 2013]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2014 ==&lt;br /&gt;
&lt;br /&gt;
Now moved to [[Books-2014|a separate page for 2014]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2015 ==&lt;br /&gt;
&lt;br /&gt;
To be moved to [[Books-2015|a separate page for 2015]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2016 ==&lt;br /&gt;
&lt;br /&gt;
To be moved to [[Books-2016|a separate page for 2016]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2017 ==&lt;br /&gt;
&lt;br /&gt;
To be moved to [[Books-2017|a separate page for 2017]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2018 ==&lt;br /&gt;
&lt;br /&gt;
To be moved to [[Books-2018|a separate page for 2018]].&lt;br /&gt;
&lt;br /&gt;
== Books from 2019 ==&lt;br /&gt;
&lt;br /&gt;
To be moved to [[Books-2019|a separate page for 2019]].&lt;br /&gt;
&lt;br /&gt;
== Books to read in the future ==&lt;br /&gt;
&lt;br /&gt;
Now moved to [[Books-future|a separate page for the future]].&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Books-2015&amp;diff=381</id>
		<title>Books-2015</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Books-2015&amp;diff=381"/>
				<updated>2019-10-01T08:52:03Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Moved content from the main Books page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=0 cellpadding=0 style=&amp;quot;margin-bottom:.5em; float:right; padding:.5em 0 .8em 1.4em; width:auto; background:inherit&amp;quot;&lt;br /&gt;
|__TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page contains a list of books (mostly fiction) that I've read together with links to the ebook version where available.&lt;br /&gt;
Apple has a free book of the week and did a promotion with a number of free books for various age groups. Starbucks give away codes for free books sometimes (on small cards near where you pick up your coffee). [http://www.smashwords.com/ Smashwords] have a number of free books, often the first book in a series.&lt;br /&gt;
&lt;br /&gt;
Previous page is [[Books-2014|Books from 2014]]&lt;br /&gt;
&lt;br /&gt;
== January 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Wanted - Nick Stephenson (Leopold Blake series)&lt;br /&gt;
* Ethan Justice: Origins - Simon Jenner&lt;br /&gt;
* The Killing League - Dani Amore&lt;br /&gt;
* Working for Bigfoot - Jim Butcher&lt;br /&gt;
* The Socket Greeny Saga book 1, Discovery - Tony Bertauski&lt;br /&gt;
* The Socket Greeny Saga book 2, Training - Tony Bertauski&lt;br /&gt;
* The Socket Greeny Saga book 3, Legend - Tony Bertauski&lt;br /&gt;
&lt;br /&gt;
* Tricknomancy - Michael A. Stackpole&lt;br /&gt;
&lt;br /&gt;
== February 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Multiple Motives - Kassandra Lamb&lt;br /&gt;
* Back on Murder (A Roland March Mystery, #1) - J. Mark Bertrand&lt;br /&gt;
* Due Justice - Diane Capri&lt;br /&gt;
&lt;br /&gt;
== March 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Fatal Distraction - Diane Capri&lt;br /&gt;
* Project ELE - Rebecca Gober &amp;amp; Courtney Nuckels&lt;br /&gt;
* Florida is murder - Diane Capri &amp;amp; Christine Kling&lt;br /&gt;
&lt;br /&gt;
== April 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Talented (book 1) - Sophie Davis&lt;br /&gt;
* Caged (book 2) - Sophie Davis&lt;br /&gt;
* Hunted (book 3) - Sophie Davis&lt;br /&gt;
&lt;br /&gt;
* Created (book 4) - Sophie Davis&lt;br /&gt;
&lt;br /&gt;
== May 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Twisted Justice - Diane Capri&lt;br /&gt;
* Working Stiff - Kevin J. Anderson&lt;br /&gt;
* Leave No Stone Unturned (Lexie Starr #1) - Jeanne Glidewell&lt;br /&gt;
* The Extinguished Guest (Lexie Starr #2) - Jeanne Glidewell&lt;br /&gt;
* Haunted (Lexie Starr #3) - Jeanne Glidewell&lt;br /&gt;
* Red Notice - Andy McNab&lt;br /&gt;
&lt;br /&gt;
== June 2015 ==&lt;br /&gt;
&lt;br /&gt;
* The Tesla Legacy - Rebecca Cantrell&lt;br /&gt;
* Rush - Eve Silver&lt;br /&gt;
* Don't Know Jack - Diane Capri (Hunt for Jack Reacher series #1)&lt;br /&gt;
* Edgewood - Karen McQuestion&lt;br /&gt;
* Omega Dog - Tim Stevens&lt;br /&gt;
* Unforeseen (Thomas Prescott #1) - Nick Pirog&lt;br /&gt;
* Trust - Pamela M. Kelley&lt;br /&gt;
&lt;br /&gt;
== July 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Slow curve on the Coquihalla - RE Donald&lt;br /&gt;
* The Forgotten Girls (Suburban Murder #1) - Alexa Steele&lt;br /&gt;
* Personal (Jack Reacher #19) - Lee Child&lt;br /&gt;
* Skin Game (Harry Dresden #15) - Jim Butcher&lt;br /&gt;
* Dance with the enemy - Rob Sinclair&lt;br /&gt;
&lt;br /&gt;
== August 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Cabal - Clive Barker&lt;br /&gt;
* Truth lies bleeding - Tony Black&lt;br /&gt;
* Misadventures of the Laundry Hag: Skeletons in the closet - Jennifer L. Hart&lt;br /&gt;
* Dream series - Dream Student - J.J. DiBenedetto&lt;br /&gt;
* Dead Line - Jack Patterson&lt;br /&gt;
* The Reordering- Vicki Pettersson&lt;br /&gt;
&lt;br /&gt;
== September 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Carmodys Run - Bill Pronzini&lt;br /&gt;
* Crimson Son - Russ Linton&lt;br /&gt;
* Uglies - Scott Westerfeld&lt;br /&gt;
* Ice on the Grapevine - RE Donald&lt;br /&gt;
&lt;br /&gt;
== October 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Becoming Alpha (Alpha Girl #1) - Aileen Erin&lt;br /&gt;
* Avoiding Alpha (Alpha Girl #2) - Aileen Erin&lt;br /&gt;
* Alpha Divided (Alpha Girl #3) - Aileen Erin&lt;br /&gt;
* Bruja (Alpha Girl #4) - Aileen Erin&lt;br /&gt;
* Alpha Unleashed (Alpha Girl #5) - Aileen Erin&lt;br /&gt;
* Dead in the Water (Cal Murphy #5) - Jack Patterson&lt;br /&gt;
&lt;br /&gt;
== November 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Jack in a Box - Diane Capri (Hunt for Jack Reacher #2)&lt;br /&gt;
* Jack and Kill - Diane Capri (Hunt for Jack Reacher #3)&lt;br /&gt;
* Get Back Jack - Diane Capri (Hunt for Jack Reacher #4)&lt;br /&gt;
* Hooked, A Thriller - Ruth Harris&lt;br /&gt;
* Blood and Snow omnibus edition - RaShelle Workman&lt;br /&gt;
** Blood and Snow BOOK 1&lt;br /&gt;
** Blood and Snow BOOK 2&lt;br /&gt;
** Blood and Snow BOOK 3&lt;br /&gt;
** Cindy Witch&lt;br /&gt;
** The Hunter's Tale&lt;br /&gt;
** Gabriel&lt;br /&gt;
** After The Kiss&lt;br /&gt;
&lt;br /&gt;
== December 2015 ==&lt;br /&gt;
&lt;br /&gt;
* Blood and Snow omnibus edition - RaShelle Workman&lt;br /&gt;
** Blood and Snow BOOK 4: The Cindy Chronicles&lt;br /&gt;
** Blood and Snow BOOK 5: Vampire Lies&lt;br /&gt;
** Blood and Snow BOOK 6: A Beauty So Beastly&lt;br /&gt;
** Blood and Snow BOOK 7: Vampire Secrets&lt;br /&gt;
** Blood and Snow BOOK 8: Asha Ever After&lt;br /&gt;
** Blood and Snow BOOK 9: Vampire Nights&lt;br /&gt;
** The Professor's Origin&lt;br /&gt;
** Blood and Snow BOOK 10.1: The Dark Moth Society, Alice&lt;br /&gt;
* Played to Death (Scott Drayco #1) - BV Lawson&lt;br /&gt;
* Gypsy Hunted - Andrea Drew&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=SSL&amp;diff=380</id>
		<title>SSL</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=SSL&amp;diff=380"/>
				<updated>2019-10-01T08:30:44Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* LetsEncrypt */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Security]]&lt;br /&gt;
== Generate a new key ==&lt;br /&gt;
&lt;br /&gt;
 openssl genrsa -out www.mydomain.com.key 2048&lt;br /&gt;
&lt;br /&gt;
== Generate a new CSR from a key ==&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -sha256 -key www.mydomain.com.key -out www.mydomain.com.csr&lt;br /&gt;
&lt;br /&gt;
To non-interactively answer the questions, use the -subj parameter.&lt;br /&gt;
&lt;br /&gt;
 -subj &amp;quot;/C=GB/ST=Nottinghamshire/L=Nottingham/O=My Company Name/CN=www.mydomain.com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
As long as the subject is at least &amp;quot;/&amp;quot;, you won't be asked any of the questions. Of course, just -subj &amp;quot;/&amp;quot; will result in a useless certificate, the minimum useful subject is probably &amp;quot;/CN=www.mydomain.com&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Generate a self-signed CRT from existing CSR ==&lt;br /&gt;
&lt;br /&gt;
 openssl x509 -signkey www.mydomain.com.key -in www.mydomain.com.csr -req -days 365 -out www.mydomain.com.crt&lt;br /&gt;
&lt;br /&gt;
== Generate a self-signed CRT and key in one go ==&lt;br /&gt;
&lt;br /&gt;
Google Chrome won't complain quite as much about this as it'll be SHA256. You'll just get the 'net::ERR_CERT_AUTHORITY_INVALID' (unknown CA) error.&lt;br /&gt;
&lt;br /&gt;
 CN=localhost.localdomain&lt;br /&gt;
 openssl req -x509 -nodes -sha256 -days 3650 -newkey rsa:2048 \&lt;br /&gt;
     -keyout /etc/pki/tls/private/$CN.key \&lt;br /&gt;
     -out /etc/pki/tls/certs/$CN.crt \&lt;br /&gt;
     -subj &amp;quot;/C=GB/O=Your Organisation/CN=$CN&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Checking if a key/csr/cert are related to each other ==&lt;br /&gt;
&lt;br /&gt;
To compare a key, CSR or certificate to check they're related (e.g the CSR from key and the certificate is the signed CSR), generate the modulus for each item and they should all be the same.&lt;br /&gt;
&lt;br /&gt;
For a certificate:&lt;br /&gt;
&lt;br /&gt;
 openssl x509 -noout -modulus -in file.crt&lt;br /&gt;
&lt;br /&gt;
For a CSR:&lt;br /&gt;
&lt;br /&gt;
 openssl req -noout -modulus -in file.csr&lt;br /&gt;
&lt;br /&gt;
For a key (assuming RSA):&lt;br /&gt;
&lt;br /&gt;
 openssl rsa -noout -modulus -in file.key&lt;br /&gt;
&lt;br /&gt;
The output for each one is (wrapped at 70 characters, normally all on one line):&lt;br /&gt;
&lt;br /&gt;
 Modulus=958F0B0961CF7F99155050CFD5DD2F3776085D560C0E4CACBACCEC6A73C38A&lt;br /&gt;
 C3DA64FE26C747AB08555522D77EE0505C69B73F7DCA064155C7EC0FADF3CC11920136&lt;br /&gt;
 DDC53C5F9BBE8B5A2866F955AFFEBFA116D8CDC6EE81CFF3F8D337FEE1E6658E507CA3&lt;br /&gt;
 7EEFC4D9BD7F679FEF0844A81A94C7CB09A52A6C3785BF2D604E2A5750D131C0C0192C&lt;br /&gt;
 E6B843BA318F08D3D0AD63837F67A6E226D9EC3E187BAA4767FD988E63DF4ED16721CF&lt;br /&gt;
 E8BC17F2BD19E8DF006D770EA5C58E894E4FA0D0B714C6AFF11F6EB821B3FE99E91E5F&lt;br /&gt;
 D9CD2019146DE7A2D264DC7FC8742E195A3A8E05EFB146C5C97FFE2815DB050E842EE8&lt;br /&gt;
 1F1C9C52A5EC7362FFB8A14E97B199&lt;br /&gt;
&lt;br /&gt;
==Convert pfx to OpenSSL key/cert pair==&lt;br /&gt;
&lt;br /&gt;
Often if you're dealing with a Windows server, you end up with a .pfx file which is a pkcs12 format certificate. In order to use it with OpenSSL on a Linux server, you need to convert the binary .pfx into a pair of files - an RSA key and PEM certificate.&lt;br /&gt;
&lt;br /&gt;
 # openssl pkcs12 -in mydomain.pfx -nocerts -out encrypted-mydomain.key&lt;br /&gt;
 Enter Import Password:&lt;br /&gt;
 MAC verified OK&lt;br /&gt;
 Enter PEM pass phrase:&lt;br /&gt;
 Verifying - Enter PEM pass phrase:&lt;br /&gt;
&lt;br /&gt;
The PEM certificate doesn't include any intermediate certificates so you may need to concatenate those onto the end of mydomain.crt depending on your configuration.&lt;br /&gt;
&lt;br /&gt;
 # openssl pkcs12 -in mydomain.pfx -clcerts -nokeys -out mydomain.crt&lt;br /&gt;
&lt;br /&gt;
==Remove passphrase from a key==&lt;br /&gt;
&lt;br /&gt;
If you followed the above instructions and entered a PEM passphrase, you can remove it so that it can be used with Apache or nginx&lt;br /&gt;
&lt;br /&gt;
 # openssl rsa -in encrypted-mydomain.key -out mydomain.key&lt;br /&gt;
&lt;br /&gt;
==LetsEncrypt==&lt;br /&gt;
&lt;br /&gt;
To use letsencrypt.org for your free SSL certificate on CentOS, without getting it to automatically change configs etc, you can use the certbot-auto script.&lt;br /&gt;
&lt;br /&gt;
 # git clone https://github.com/letsencrypt/letsencrypt&lt;br /&gt;
 # cd letsencrypt&lt;br /&gt;
 # ./certbot-auto&lt;br /&gt;
&lt;br /&gt;
Once it's updated itself and installed any dependencies, it can be used to generate the SSL certificates.&lt;br /&gt;
&lt;br /&gt;
 # ./certbot-auto certonly --webroot -d www.example.com -d example.com -w /var/www/html/example.com&lt;br /&gt;
&lt;br /&gt;
The -d option needs to be repeated for all ServerName and ServerAlias directives used for the site you're trying to secure. -w specifies the webroot to use for the authentication process (a file is created in there which is then requested by LetsEncrypt)&lt;br /&gt;
&lt;br /&gt;
If all goes well, you'll see a message like this:&lt;br /&gt;
&lt;br /&gt;
 - Congratulations! Your certificate and chain have been saved at&lt;br /&gt;
   /etc/letsencrypt/live/www.example.com/fullchain.pem. Your cert&lt;br /&gt;
   will expire on 2016-09-21. To obtain a new or tweaked version of&lt;br /&gt;
   this certificate in the future, simply run certbot-auto again. To&lt;br /&gt;
   non-interactively renew *all* of your certificates, run&lt;br /&gt;
   &amp;quot;certbot-auto renew&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The other files are also in the /etc/letsencrypt/live/www.example.com/ directory and can be used as follows in your apache config. The SSLCipherSuite, SSLProtocol and SSLHonorCipherOrder lines result in an 'A' rating at [https://www.ssllabs.com/ SSL Labs server test]&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;VirtualHost 10.20.30.40:443&amp;gt;&lt;br /&gt;
 ServerName www.example.com&lt;br /&gt;
 ServerAlias example.com&lt;br /&gt;
 DocumentRoot /var/www/html/example.com&lt;br /&gt;
 SSLEngine on&lt;br /&gt;
 SSLProtocol all -SSLv2 -SSLv3&lt;br /&gt;
 SSLCipherSuite EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4&lt;br /&gt;
 SSLHonorCipherOrder on&lt;br /&gt;
 SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem&lt;br /&gt;
 SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem&lt;br /&gt;
 SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem&lt;br /&gt;
 &amp;lt;/VirtualHost&amp;gt;&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=LVM&amp;diff=379</id>
		<title>LVM</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=LVM&amp;diff=379"/>
				<updated>2019-09-27T08:18:41Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Extending a filesystem to include a new partition */ added info about creating new LV&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Creating new volumes ==&lt;br /&gt;
&lt;br /&gt;
Assuming that &amp;lt;code&amp;gt;/dev/sdb&amp;lt;/code&amp;gt; is a new disk with a single full size partition &amp;lt;code&amp;gt;/dev/sdb1&amp;lt;/code&amp;gt;, the following will create a new volume group called &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; and a couple of logical volumes inside called &amp;lt;code&amp;gt;projects&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;backups&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # vgcreate data /dev/sdb1&lt;br /&gt;
 &lt;br /&gt;
 # lvcreate -n projects -L 20G data&lt;br /&gt;
 # lvcreate -n backups -l 100%FREE data&lt;br /&gt;
&lt;br /&gt;
== Extending a filesystem to include a new partition ==&lt;br /&gt;
&lt;br /&gt;
'''IMPORTANT: Check the partitions, do not just copy/paste below!'''&lt;br /&gt;
&lt;br /&gt;
Initialise the LVM metadata on the partition to add into the filesystem&lt;br /&gt;
&lt;br /&gt;
 # pvcreate /dev/sdb1&lt;br /&gt;
&lt;br /&gt;
Add the partition to the volume group&lt;br /&gt;
&lt;br /&gt;
 # vgextend sys /dev/sdb1&lt;br /&gt;
   Volume group &amp;quot;sys&amp;quot; successfully extended&lt;br /&gt;
&lt;br /&gt;
Extend the relevant logical volume to include all of the newly added space&lt;br /&gt;
&lt;br /&gt;
 # lvextend -l +100%FREE /dev/sys/root&lt;br /&gt;
  Size of logical volume sys/root changed from 27.88 GiB (892 extents) to 47.84 GiB (1531 extents).&lt;br /&gt;
  Logical volume root successfully resized&lt;br /&gt;
&lt;br /&gt;
Resize the underlying filesystem to use the whole LVM device&lt;br /&gt;
&lt;br /&gt;
 # resize2fs /dev/sys/root&lt;br /&gt;
 resize2fs 1.41.12 (17-May-2010)&lt;br /&gt;
 Filesystem at /dev/sys/root is mounted on /; on-line resizing required&lt;br /&gt;
 old desc_blocks = 2, new_desc_blocks = 3&lt;br /&gt;
 Performing an on-line resize of /dev/sys/root to 12541952 (4k) blocks.&lt;br /&gt;
 The filesystem on /dev/sys/root is now 12541952 blocks long.&lt;br /&gt;
&lt;br /&gt;
== Mounting a filesystem from a Xen disk file that has LVM on it ==&lt;br /&gt;
&lt;br /&gt;
 # losetup /dev/loop7 xenguest1.xvda.img&lt;br /&gt;
 # kpartx -v -a xenguest1.xvda.img&lt;br /&gt;
&lt;br /&gt;
If the disk partitions were just normal ones, you would be able to mount them now as /dev/loop7p1 /dev/loop7p2 etc. If the filesystems are contained within an LVM volume group there are some extra steps.&lt;br /&gt;
&lt;br /&gt;
Scan physical volumes for LVM partitions&lt;br /&gt;
&lt;br /&gt;
 # pvscan&lt;br /&gt;
 PV /dev/mapper/loop7p2   VG vg_xenguest1  lvm2 [29.51 GiB / 0    free]&lt;br /&gt;
&lt;br /&gt;
Scan the partitions for volume groups&lt;br /&gt;
&lt;br /&gt;
 # vgscan&lt;br /&gt;
 Reading all physical volumes.  This may take a while...&lt;br /&gt;
 Found volume group &amp;quot;vg_xenguest1&amp;quot; using metadata type lvm2&lt;br /&gt;
&lt;br /&gt;
Scan for logical volumes. Any that are currently in use will show ACTIVE in the first column.&lt;br /&gt;
&lt;br /&gt;
 # lvscan&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_root' [28.54 GiB] inherit&lt;br /&gt;
  inactive   '/dev/vg_xenguest1/lv_swap' [992.00 MiB] inherit&lt;br /&gt;
&lt;br /&gt;
Since these are inactive, they can't be used as devices (yet).&lt;br /&gt;
&lt;br /&gt;
 # lvdisplay /dev/vg_xenguest1/lv_root&lt;br /&gt;
 ...&lt;br /&gt;
  LV Status              NOT available&lt;br /&gt;
  LV Size                28.54 GiB&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
First we need to set the volume group active, and then the logical volumes should work fine.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -ay vg_xenguest1&lt;br /&gt;
 2 logical volume(s) in volume group &amp;quot;vg_xenguest1&amp;quot; now active&lt;br /&gt;
&lt;br /&gt;
And now we can mount the root filesystem.&lt;br /&gt;
&lt;br /&gt;
 # mkdir /mnt/xenguest1&lt;br /&gt;
 # mount -t ext3 /dev/mapper/vg_xenguest1/lv_root /mnt/xenguest1&lt;br /&gt;
&lt;br /&gt;
When you're finished with it, use the following commands to make the volumes inactive, remove the partitions from the kernel partition map and then remove the loopback device.&lt;br /&gt;
&lt;br /&gt;
 # vgchange -an vg_xenguest1 &lt;br /&gt;
 # kpartx -v -d /dev/loop7&lt;br /&gt;
 # losetup -d /dev/loop7&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=CentOS7&amp;diff=378</id>
		<title>CentOS7</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=CentOS7&amp;diff=378"/>
				<updated>2019-09-27T07:17:32Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Enable firewall */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also [[Upstart]]&lt;br /&gt;
&lt;br /&gt;
== Change server hostname ==&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# hostnamectl status&lt;br /&gt;
 &lt;br /&gt;
   Static hostname: localhost.localdomain&lt;br /&gt;
         Icon name: computer-vm&lt;br /&gt;
           Chassis: vm&lt;br /&gt;
        Machine ID: 399b74f54385ee0d782648666a204c25&lt;br /&gt;
           Boot ID: 411893b81fee4fb0b865e1b18fd8dd6d&lt;br /&gt;
    Virtualization: kvm&lt;br /&gt;
  Operating System: CentOS Linux 7 (Core)&lt;br /&gt;
       CPE OS Name: cpe:/o:centos:centos:7&lt;br /&gt;
            Kernel: Linux 3.10.0-123.el7.x86_64&lt;br /&gt;
      Architecture: x86_64&lt;br /&gt;
&lt;br /&gt;
Set the hostname.&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# hostnamectl set-hostname centos7.internal&lt;br /&gt;
&lt;br /&gt;
Check the host name again (Close the session and open new session using putty or console)&lt;br /&gt;
&lt;br /&gt;
== CentOS7 kernel panic on some hardware ==&lt;br /&gt;
&lt;br /&gt;
If you can't even get the installer to work and it just causes a kernel panic on startup, check this link: http://centosfaq.org/centos/centos-72-kernel-panic/&lt;br /&gt;
&lt;br /&gt;
The relevant info is pasted below in case the page is removed in the future.&lt;br /&gt;
&lt;br /&gt;
During the startup of the installer, edit the options for the kernel to include:&lt;br /&gt;
&lt;br /&gt;
 initcall_blacklist=clocksource_done_booting&lt;br /&gt;
&lt;br /&gt;
If the machine is already installed and you're moving the disks to another system and get a kernel panic, it's possible to use an older rescue disk and&lt;br /&gt;
&lt;br /&gt;
Append the line&lt;br /&gt;
&lt;br /&gt;
 GRUB_CMDLINE_LINUX_DEFAULT=”initcall_blacklist=clocksource_done_booting”&lt;br /&gt;
&lt;br /&gt;
to /etc/default/grub, and run&lt;br /&gt;
&lt;br /&gt;
 # grub2-mkconfig &amp;gt; /boot/grub2/grub.cfg&lt;br /&gt;
&lt;br /&gt;
On reboot this should allow you to boot succesfully.&lt;br /&gt;
&lt;br /&gt;
== Enable firewall ==&lt;br /&gt;
&lt;br /&gt;
Start the firewall running and set it to auto-start on bootup&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# systemctl start firewalld&lt;br /&gt;
 [root@localhost ~]# systemctl enable firewalld&lt;br /&gt;
&lt;br /&gt;
Enable HTTP and HTTPS&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=http&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=https&lt;br /&gt;
&lt;br /&gt;
Add a custom port for SSH&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-port=22222/tcp&lt;br /&gt;
&lt;br /&gt;
Remove the original SSH service&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --remove-service=ssh&lt;br /&gt;
&lt;br /&gt;
Add a rule for access to a service on a specific local port from a specific source IP&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public \&lt;br /&gt;
     --add-rich-rule='rule family=&amp;quot;ipv4&amp;quot; source address=&amp;quot;1.2.3.0/24&amp;quot;&lt;br /&gt;
     port protocol=&amp;quot;tcp&amp;quot; port=&amp;quot;22222&amp;quot; accept'&lt;br /&gt;
&lt;br /&gt;
Block a single IP from all services (and yes, that's a real IP that was pounding on a WordPress login page)&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --add-rich-rule=&amp;quot;rule family='ipv4' source address='176.28.22.192' reject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Reload the firewall rules&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --reload&lt;br /&gt;
&lt;br /&gt;
Add port forwarding for port 22 to port 922 on the same machine&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --add-forward-port=port=22:proto=tcp:toport=922&lt;br /&gt;
&lt;br /&gt;
== Disable firewalld and use iptables ==&lt;br /&gt;
&lt;br /&gt;
(content taken from racktables.com in case it disappears)&lt;br /&gt;
&lt;br /&gt;
The first step is to stop and mask the firewalld service (i.e., the service you do not want to use):&lt;br /&gt;
&lt;br /&gt;
 $ systemctl stop firewalld&lt;br /&gt;
 $ systemctl mask firewalld&lt;br /&gt;
&lt;br /&gt;
Then, install the &amp;quot;iptables-services&amp;quot; package (if it is not already installed):&lt;br /&gt;
&lt;br /&gt;
 $ yum install iptables-services&lt;br /&gt;
&lt;br /&gt;
Enable the service to start at boot-time:&lt;br /&gt;
&lt;br /&gt;
 $ systemctl enable iptables&lt;br /&gt;
&lt;br /&gt;
If you are saving your rules in that /etc/sysconfig/iptables file, you will then need to run one of the following commands:&lt;br /&gt;
&lt;br /&gt;
 $ service iptables restart  # OR:&lt;br /&gt;
 $ systemctl restart iptables&lt;br /&gt;
&lt;br /&gt;
Next, check that the iptables service is &amp;quot;active&amp;quot; with:&lt;br /&gt;
&lt;br /&gt;
 $ systemctl status iptables&lt;br /&gt;
&lt;br /&gt;
You can query the systemd journal for a &amp;quot;log&amp;quot; of the changes you made to the iptables service with:&lt;br /&gt;
&lt;br /&gt;
 $ journalctl -f -u iptables.service&lt;br /&gt;
&lt;br /&gt;
== Enable disk quota on ext4 ==&lt;br /&gt;
&lt;br /&gt;
Add to /etc/fstab the following options on the line with the ext4 fs (eg /home):&lt;br /&gt;
&lt;br /&gt;
 usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0&lt;br /&gt;
&lt;br /&gt;
Then check quotas and enable them&lt;br /&gt;
&lt;br /&gt;
 # quotaoff -a&lt;br /&gt;
 # quotacheck -auvgm&lt;br /&gt;
 # quotaon -a&lt;br /&gt;
&lt;br /&gt;
To check the quotas&lt;br /&gt;
&lt;br /&gt;
 # repquota -auv&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=CSS&amp;diff=377</id>
		<title>CSS</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=CSS&amp;diff=377"/>
				<updated>2019-09-13T09:45:54Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Tip about page breaks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Page breaks when printing ==&lt;br /&gt;
&lt;br /&gt;
Extract from https://davidwalsh.name/css-page-breaks&lt;br /&gt;
&lt;br /&gt;
=== The CSS ===&lt;br /&gt;
&lt;br /&gt;
The all and print medias should be addressed:&lt;br /&gt;
&lt;br /&gt;
 @media all {&lt;br /&gt;
     .page-break    { display: none; }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 @media print {&lt;br /&gt;
     .page-break    { display: block; page-break-before: always; }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The first declaration ensures that the page-break is never seen visually...while the second ensures that the page break is seen by the printer.&lt;br /&gt;
&lt;br /&gt;
=== The HTML ===&lt;br /&gt;
&lt;br /&gt;
Creating a simple DIV element with the page-break class is how you implement the page break.&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;div class=&amp;quot;page-break&amp;quot;&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:WebDevelopment]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Images&amp;diff=376</id>
		<title>Images</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Images&amp;diff=376"/>
				<updated>2019-08-21T13:56:21Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: imagemagick tricks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Changing colours with ImageMagick ==&lt;br /&gt;
&lt;br /&gt;
Converting true black rgb(0,0,0) in an image to rgb(0,0,10) to force composite black:&lt;br /&gt;
&lt;br /&gt;
 name=MyLogoImage.png&lt;br /&gt;
 convert &amp;quot;$name&amp;quot; -depth 32 -type TrueColorMatte -alpha set -channel RGBA -fill 'rgb(0,0,10)' -opaque 'rgb(0,0,0)' &amp;quot;PNG32:new-$name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This will create a file called new-MyLogoImage.png that should have the same properties shown by the &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; command. The difference will be that the black is no longer true black and is suitable for use with LG Plates.&lt;br /&gt;
&lt;br /&gt;
 MyLogoImage.png: PNG image data, 522 x 97, 8-bit/color RGBA, non-interlaced&lt;br /&gt;
&lt;br /&gt;
The RGBA provides the alpha channel (partial transparency) which is sometimes used for smoother edges rather than using shades of the main colour.&lt;br /&gt;
&lt;br /&gt;
A similar command could be used to &amp;lt;code&amp;gt;-fill 'rgb(250,250,250)' -opaque 'rgb(255,255,255)'&amp;lt;/code&amp;gt; replace pure white with off-white for use with a Pro printer. There may be some fuzzing required (-fuzz 5% for example) where badges use a shade of white such as rgb(253,253,253) since this wouldn't be picked up as exactly rgb(255,255,255) but would still be translated by the printer into transparency. The actual fuzz value may need some experimentation.&lt;br /&gt;
&lt;br /&gt;
== Extend image and fill new canvas ==&lt;br /&gt;
&lt;br /&gt;
Extend the file to 590x4015 from whatever the current size is. Centre the original image on the new canvas and fill the extra canvas with solid blue (#0000ff). The new image has the colour depth adjusted to the minimum so it's quite a good way of shrinking the files.&lt;br /&gt;
&lt;br /&gt;
 -rw-rw-r-- 1 plates plates 11216 Nov 14 12:14 Union Flag Eng 2.png&lt;br /&gt;
 Union Flag Eng 2.png: PNG image data, 590 x 2480, 8-bit colormap, non-interlaced&lt;br /&gt;
&lt;br /&gt;
 convert &amp;quot;$name&amp;quot; -background blue -gravity Center -depth 32 -extent '590x4015' &amp;quot;new-$name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 -rw-r--r-- 1 plates plates  4640 Dec 14 15:52 new-Union Flag Eng 2.png&lt;br /&gt;
 new-Union Flag Eng 2.png:     PNG image data, 590 x 4015, 2-bit colormap, non-interlaced&lt;br /&gt;
&lt;br /&gt;
== Convert transparent background to white ==&lt;br /&gt;
&lt;br /&gt;
Replace white with any other colour as required!&lt;br /&gt;
&lt;br /&gt;
 convert transparentbgimage.png -transparent-color white -background white -layers flatten -depth 32 outputimage.png&lt;br /&gt;
&lt;br /&gt;
== Colour Picker app ==&lt;br /&gt;
&lt;br /&gt;
Highly recommended! http://instant-eyedropper.com/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Contact Sheet with ImageMagick ==&lt;br /&gt;
&lt;br /&gt;
 montage -verbose -label '%f' -pointsize 14 \&lt;br /&gt;
    -background 'white' -fill 'black' \&lt;br /&gt;
    -define jpeg:size=300x300 -geometry 300x300+2+2 \&lt;br /&gt;
    -auto-orient *.png ../output.png&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-label '%f'&amp;lt;/code&amp;gt; specifies to use the filename as a label for each image&lt;br /&gt;
&amp;lt;code&amp;gt;-tile 10x&amp;lt;/code&amp;gt; makes it output 10 badges per row&lt;br /&gt;
&lt;br /&gt;
== Count the unique colours in an image ==&lt;br /&gt;
&lt;br /&gt;
This can be useful if an image won't reduce in size by much (e.g to an 8 bit colour map).&lt;br /&gt;
&lt;br /&gt;
 $ file MyImage.png&lt;br /&gt;
 MyImage.png:     PNG image data, 400 x 400, 8-bit/color RGB, non-interlaced&lt;br /&gt;
&lt;br /&gt;
ImageMagick has a command to count how many colours there are in an image:&lt;br /&gt;
&lt;br /&gt;
 $ identify -format %k MyImage.png&lt;br /&gt;
 2310&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Windows10&amp;diff=375</id>
		<title>Windows10</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Windows10&amp;diff=375"/>
				<updated>2019-05-15T07:51:03Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Checksum files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Enabling the Windows 10 lock screen image information ==&lt;br /&gt;
&lt;br /&gt;
Click on Start &amp;gt; Run and type '''control userpasswords2''' to open the user management dialog. Click on the Advanced tab and untick the checkbox at the bottom for ''Require users to press Ctrl-Alt-Delete''&lt;br /&gt;
&lt;br /&gt;
== Comparison of files or folders ==&lt;br /&gt;
&lt;br /&gt;
Install '''WinMerge''' from [http://winmerge.org/ winmerge.org] - it includes a shell extension to allow easy comparison of files or folders.&lt;br /&gt;
&lt;br /&gt;
== View image EXIF data ==&lt;br /&gt;
&lt;br /&gt;
Picture Information Extractor (PIE) - free download&lt;br /&gt;
&lt;br /&gt;
* [https://www.picmeta.com/download.htm picmeta.com]&lt;br /&gt;
&lt;br /&gt;
== Checksum files ==&lt;br /&gt;
&lt;br /&gt;
Works in Windows 7 and 8 too.&lt;br /&gt;
&lt;br /&gt;
 certutil -HashFile filename.zip MD5&lt;br /&gt;
 certutil -HashFile filename.zip SHA1&lt;br /&gt;
&lt;br /&gt;
== MacOS QuickLook for Windows ==&lt;br /&gt;
&lt;br /&gt;
It allows user peek into a file content in lightning speed by just pressing the Space key.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/QL-Win/QuickLook QuickLook for Windows]&lt;br /&gt;
&lt;br /&gt;
== Ditto - multi-buffer clipboard ==&lt;br /&gt;
&lt;br /&gt;
[https://ditto-cp.sourceforge.io/ Direct from SourceForge] or via the [https://www.microsoft.com/en-us/p/ditto-clipboard/9nblggh3zbjq Microsoft Store]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Firefox&amp;diff=374</id>
		<title>Firefox</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Firefox&amp;diff=374"/>
				<updated>2018-11-29T09:01:52Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Some useful options for about:config&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!|Preference&lt;br /&gt;
!|Value&lt;br /&gt;
!|Use&lt;br /&gt;
|-&lt;br /&gt;
||browser.newtabpage.activity-stream.topSitesRows&lt;br /&gt;
||2 (increase as required)&lt;br /&gt;
||Add more than 2 rows of 'top sites'&lt;br /&gt;
|-&lt;br /&gt;
||network.IDN_show_punycode&lt;br /&gt;
||true&lt;br /&gt;
||Show IDNs as xn--.... in the address bar&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Addons ==&lt;br /&gt;
&lt;br /&gt;
Make the background on standalone images properly transparent&lt;br /&gt;
&lt;br /&gt;
* https://addons.mozilla.org/en-US/firefox/addon/transparent-standalone-image/&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Firefox&amp;diff=373</id>
		<title>Firefox</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Firefox&amp;diff=373"/>
				<updated>2018-11-20T08:34:54Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Some useful options for about:config&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!|Preference&lt;br /&gt;
!|Value&lt;br /&gt;
!|Use&lt;br /&gt;
|-&lt;br /&gt;
||browser.newtabpage.activity-stream.topSitesRows&lt;br /&gt;
||2 (increase as required)&lt;br /&gt;
||Add more than 2 rows of 'top sites'&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Addons ==&lt;br /&gt;
&lt;br /&gt;
Make the background on standalone images properly transparent&lt;br /&gt;
&lt;br /&gt;
* https://addons.mozilla.org/en-US/firefox/addon/transparent-standalone-image/&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Nginx&amp;diff=372</id>
		<title>Nginx</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Nginx&amp;diff=372"/>
				<updated>2018-11-13T12:25:48Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Custom error pages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To use nginx as a proxy - for example from an old server to a new one during a migration, you need to set the Host header to be $host&lt;br /&gt;
&lt;br /&gt;
There are also some other headers that could be useful so just set the whole lot in the global part of /etc/nginx/conf.d/default.conf&lt;br /&gt;
&lt;br /&gt;
 proxy_set_header    Host                $host;&lt;br /&gt;
 proxy_set_header    Connection          &amp;quot;&amp;quot;;&lt;br /&gt;
 proxy_set_header    X-Real-IP           $remote_addr;&lt;br /&gt;
 proxy_set_header    X-Forwarded-Port    $server_port;&lt;br /&gt;
&lt;br /&gt;
Setup the server to listen either on every interface port 80, or a specific IP on port 80 using the listen directive.&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
    listen      80 default_server;&lt;br /&gt;
    listen      [2a02:af8:3:2000::7982]:80 default_server;&lt;br /&gt;
    server_name _;&lt;br /&gt;
&lt;br /&gt;
And make sure that the entire site from / downwards is proxied through to the new IP address&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        proxy_pass http://213.229.84.27;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If using nginx to proxy to an application such as [http://gitea.io/ gitea], when pushing a large repository you may get an HTTP 413 error.&lt;br /&gt;
&lt;br /&gt;
 Delta compression using up to 4 threads.&lt;br /&gt;
 Compressing objects: 100% (2688/2688), done.&lt;br /&gt;
 error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large&lt;br /&gt;
 fatal: The remote end hung up unexpectedly&lt;br /&gt;
 Writing objects: 100% (2756/2756), 845.89 MiB | 26.77 MiB/s, done.&lt;br /&gt;
 Total 2756 (delta 674), reused 0 (delta 0)&lt;br /&gt;
 fatal: The remote end hung up unexpectedly&lt;br /&gt;
&lt;br /&gt;
The reason is that nginx buffers proxied requests by default and git is trying to push the whole thing in a single request. The quick solution is to increase ''client_max_body_size'' to something large enough - for example, 2GB.&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
     ...&lt;br /&gt;
     client_max_body_size 2000m;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In addition to this, you may wish to disable request buffering:&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
     ...&lt;br /&gt;
     location / {&lt;br /&gt;
         ...&lt;br /&gt;
         proxy_http_version 1.1;&lt;br /&gt;
         proxy_request_buffering off;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Custom error pages ==&lt;br /&gt;
&lt;br /&gt;
Proxying to a backend server (such as Catalyst+starman) but returning any files which actually exist in /var/www/html such as CSS or JavaScript files.&lt;br /&gt;
&lt;br /&gt;
        root /var/www/html;&lt;br /&gt;
 &lt;br /&gt;
        location / {&lt;br /&gt;
                try_files $uri @starman;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        location @starman {&lt;br /&gt;
                proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
                proxy_set_header X-Forwarded-For $remote_addr;&lt;br /&gt;
                proxy_set_header SSL on;&lt;br /&gt;
                proxy_set_header X-Forwarded-Proto https;&lt;br /&gt;
                proxy_set_header Host $host;&lt;br /&gt;
                proxy_pass http://127.0.0.1:3003;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
If there's an error (for example the backend server is down) you'll get a &amp;quot;502 Bad Gateway&amp;quot; response from nginx. To output a static HTML page, you can use the error_page directive&lt;br /&gt;
&lt;br /&gt;
 error_page 502 /error.html&lt;br /&gt;
&lt;br /&gt;
This works fine except that the response code 502 is replaced with a 200 and this will cause your error page to be cached by Google etc. Instead of the above, add a section as follows.&lt;br /&gt;
&lt;br /&gt;
        error_page 503 =503 @proxyisdown;&lt;br /&gt;
        error_page 502 =502 @proxyisdown;&lt;br /&gt;
 &lt;br /&gt;
        location @proxyisdown {&lt;br /&gt;
                rewrite ^.*$ /error.html break;&lt;br /&gt;
                add_header Retry-After 600;&lt;br /&gt;
                expires 1s;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
This causes the status code to be returned still, but outputs the content from the page error.html (located in the root). The rewrite to ignore any path is required otherwise a valid url handled by the backend (e.g. /login) will return a &amp;quot;404 Not found&amp;quot; if the backend is down. This is because it attempts to return the content of /var/www/html/login which doesn't exist.&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Nginx&amp;diff=371</id>
		<title>Nginx</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Nginx&amp;diff=371"/>
				<updated>2018-11-13T12:25:32Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Custom error pages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To use nginx as a proxy - for example from an old server to a new one during a migration, you need to set the Host header to be $host&lt;br /&gt;
&lt;br /&gt;
There are also some other headers that could be useful so just set the whole lot in the global part of /etc/nginx/conf.d/default.conf&lt;br /&gt;
&lt;br /&gt;
 proxy_set_header    Host                $host;&lt;br /&gt;
 proxy_set_header    Connection          &amp;quot;&amp;quot;;&lt;br /&gt;
 proxy_set_header    X-Real-IP           $remote_addr;&lt;br /&gt;
 proxy_set_header    X-Forwarded-Port    $server_port;&lt;br /&gt;
&lt;br /&gt;
Setup the server to listen either on every interface port 80, or a specific IP on port 80 using the listen directive.&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
    listen      80 default_server;&lt;br /&gt;
    listen      [2a02:af8:3:2000::7982]:80 default_server;&lt;br /&gt;
    server_name _;&lt;br /&gt;
&lt;br /&gt;
And make sure that the entire site from / downwards is proxied through to the new IP address&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        proxy_pass http://213.229.84.27;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If using nginx to proxy to an application such as [http://gitea.io/ gitea], when pushing a large repository you may get an HTTP 413 error.&lt;br /&gt;
&lt;br /&gt;
 Delta compression using up to 4 threads.&lt;br /&gt;
 Compressing objects: 100% (2688/2688), done.&lt;br /&gt;
 error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large&lt;br /&gt;
 fatal: The remote end hung up unexpectedly&lt;br /&gt;
 Writing objects: 100% (2756/2756), 845.89 MiB | 26.77 MiB/s, done.&lt;br /&gt;
 Total 2756 (delta 674), reused 0 (delta 0)&lt;br /&gt;
 fatal: The remote end hung up unexpectedly&lt;br /&gt;
&lt;br /&gt;
The reason is that nginx buffers proxied requests by default and git is trying to push the whole thing in a single request. The quick solution is to increase ''client_max_body_size'' to something large enough - for example, 2GB.&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
     ...&lt;br /&gt;
     client_max_body_size 2000m;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In addition to this, you may wish to disable request buffering:&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
     ...&lt;br /&gt;
     location / {&lt;br /&gt;
         ...&lt;br /&gt;
         proxy_http_version 1.1;&lt;br /&gt;
         proxy_request_buffering off;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Custom error pages ==&lt;br /&gt;
&lt;br /&gt;
Proxying to a backend server (such as Catalyst+starman) but returning any files which actually exist in /var/www/html such as CSS or JavaScript files.&lt;br /&gt;
&lt;br /&gt;
        root /var/www/html;&lt;br /&gt;
 &lt;br /&gt;
        location / {&lt;br /&gt;
                try_files $uri @starman;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        location @starman {&lt;br /&gt;
                proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
                proxy_set_header X-Forwarded-For $remote_addr;&lt;br /&gt;
                proxy_set_header SSL on;&lt;br /&gt;
                proxy_set_header X-Forwarded-Proto https;&lt;br /&gt;
                proxy_set_header Host $host;&lt;br /&gt;
                proxy_pass http://127.0.0.1:3003;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
If there's an error (for example the backend server is down) you'll get a &amp;quot;502 Bad Gateway&amp;quot; response from nginx. To output a static HTML page, you can use the error_page directive&lt;br /&gt;
&lt;br /&gt;
 error_page 502 /error.html&lt;br /&gt;
&lt;br /&gt;
This works fine except that the response code 502 is replaced with a 200 and this will cause your error page to be cached by Google etc. Instead of the above, add a section as follows.&lt;br /&gt;
&lt;br /&gt;
        error_page 503 =503 @proxyisdown;&lt;br /&gt;
        error_page 502 =502 @proxyisdown;&lt;br /&gt;
 &lt;br /&gt;
        location @proxyisdown {&lt;br /&gt;
                rewrite ^.*$ /error.html break;&lt;br /&gt;
                add_header Retry-After 600;&lt;br /&gt;
                expires 1s;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
This causes the status code to be returned still, but outputs the content from the page error.html (located in the root). The rewrite to ignore any path is required otherwise a valid url handled by the backend (e.g. /login) will return a &amp;quot;404 Not found&amp;quot; if the backend is down. This is because it attempts to return the content of /var/www/html/login which doesn't exist.&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Nginx&amp;diff=370</id>
		<title>Nginx</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Nginx&amp;diff=370"/>
				<updated>2018-11-13T12:25:17Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: nginx proxying and handling unavailable backend servers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To use nginx as a proxy - for example from an old server to a new one during a migration, you need to set the Host header to be $host&lt;br /&gt;
&lt;br /&gt;
There are also some other headers that could be useful so just set the whole lot in the global part of /etc/nginx/conf.d/default.conf&lt;br /&gt;
&lt;br /&gt;
 proxy_set_header    Host                $host;&lt;br /&gt;
 proxy_set_header    Connection          &amp;quot;&amp;quot;;&lt;br /&gt;
 proxy_set_header    X-Real-IP           $remote_addr;&lt;br /&gt;
 proxy_set_header    X-Forwarded-Port    $server_port;&lt;br /&gt;
&lt;br /&gt;
Setup the server to listen either on every interface port 80, or a specific IP on port 80 using the listen directive.&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
    listen      80 default_server;&lt;br /&gt;
    listen      [2a02:af8:3:2000::7982]:80 default_server;&lt;br /&gt;
    server_name _;&lt;br /&gt;
&lt;br /&gt;
And make sure that the entire site from / downwards is proxied through to the new IP address&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        proxy_pass http://213.229.84.27;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If using nginx to proxy to an application such as [http://gitea.io/ gitea], when pushing a large repository you may get an HTTP 413 error.&lt;br /&gt;
&lt;br /&gt;
 Delta compression using up to 4 threads.&lt;br /&gt;
 Compressing objects: 100% (2688/2688), done.&lt;br /&gt;
 error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large&lt;br /&gt;
 fatal: The remote end hung up unexpectedly&lt;br /&gt;
 Writing objects: 100% (2756/2756), 845.89 MiB | 26.77 MiB/s, done.&lt;br /&gt;
 Total 2756 (delta 674), reused 0 (delta 0)&lt;br /&gt;
 fatal: The remote end hung up unexpectedly&lt;br /&gt;
&lt;br /&gt;
The reason is that nginx buffers proxied requests by default and git is trying to push the whole thing in a single request. The quick solution is to increase ''client_max_body_size'' to something large enough - for example, 2GB.&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
     ...&lt;br /&gt;
     client_max_body_size 2000m;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In addition to this, you may wish to disable request buffering:&lt;br /&gt;
&lt;br /&gt;
 server {&lt;br /&gt;
     ...&lt;br /&gt;
     location / {&lt;br /&gt;
         ...&lt;br /&gt;
         proxy_http_version 1.1;&lt;br /&gt;
         proxy_request_buffering off;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Custom error pages ==&lt;br /&gt;
&lt;br /&gt;
Proxying to a backend server (such as Catalyst+starman) but returning any files which actually exist in /var/www/html such as CSS or JavaScript files.&lt;br /&gt;
&lt;br /&gt;
        root /var/www/html;&lt;br /&gt;
&lt;br /&gt;
        location / {&lt;br /&gt;
                try_files $uri @starman;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        location @starman {&lt;br /&gt;
                proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
                proxy_set_header X-Forwarded-For $remote_addr;&lt;br /&gt;
                proxy_set_header SSL on;&lt;br /&gt;
                proxy_set_header X-Forwarded-Proto https;&lt;br /&gt;
                proxy_set_header Host $host;&lt;br /&gt;
                proxy_pass http://127.0.0.1:3003;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
If there's an error (for example the backend server is down) you'll get a &amp;quot;502 Bad Gateway&amp;quot; response from nginx. To output a static HTML page, you can use the error_page directive&lt;br /&gt;
&lt;br /&gt;
 error_page 502 /error.html&lt;br /&gt;
&lt;br /&gt;
This works fine except that the response code 502 is replaced with a 200 and this will cause your error page to be cached by Google etc. Instead of the above, add a section as follows.&lt;br /&gt;
&lt;br /&gt;
        error_page 503 =503 @proxyisdown;&lt;br /&gt;
        error_page 502 =502 @proxyisdown;&lt;br /&gt;
&lt;br /&gt;
        location @proxyisdown {&lt;br /&gt;
                rewrite ^.*$ /error.html break;&lt;br /&gt;
                add_header Retry-After 600;&lt;br /&gt;
                expires 1s;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
This causes the status code to be returned still, but outputs the content from the page error.html (located in the root). The rewrite to ignore any path is required otherwise a valid url handled by the backend (e.g. /login) will return a &amp;quot;404 Not found&amp;quot; if the backend is down. This is because it attempts to return the content of /var/www/html/login which doesn't exist.&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Postfix&amp;diff=369</id>
		<title>Postfix</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Postfix&amp;diff=369"/>
				<updated>2018-10-16T07:33:38Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Added postfix notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== DKIM ==&lt;br /&gt;
&lt;br /&gt;
DKIM notes copied from https://www.linuxtechi.com/configure-domainkeys-with-postfix-on-centos-7/ (in case they disappear).&lt;br /&gt;
&lt;br /&gt;
Enable EPEL repo&lt;br /&gt;
&lt;br /&gt;
 # yum install epel-release&lt;br /&gt;
&lt;br /&gt;
Install OpenDKIM package and generate the default keys&lt;br /&gt;
&lt;br /&gt;
 # yum install -y opendkim&lt;br /&gt;
 # opendkim-default-keygen&lt;br /&gt;
 Generating default DKIM keys:&lt;br /&gt;
 Default DKIM keys for freshdaymall.com created in /etc/opendkim/keys.&lt;br /&gt;
 #&lt;br /&gt;
&lt;br /&gt;
In /etc/opendkim/keys/ are two files - default.private (used for signing the emails) and default.txt (public key to be published in DNS). A selector 'default' is created.&lt;br /&gt;
&lt;br /&gt;
Edit the following config files:&lt;br /&gt;
&lt;br /&gt;
* /etc/opendkim.conf&lt;br /&gt;
&lt;br /&gt;
 Mode sv&lt;br /&gt;
 Socket inet:8891@127.0.0.1&lt;br /&gt;
 Canonicalization relaxed/simple&lt;br /&gt;
 Domain ''yourdomain.com''&lt;br /&gt;
 #KeyFile /etc/opendkim/keys/default.private&lt;br /&gt;
 KeyTable refile:/etc/opendkim/KeyTable&lt;br /&gt;
 SigningTable refile:/etc/opendkim/SigningTable&lt;br /&gt;
 ExternalIgnoreList refile:/etc/opendim/TrustedHosts&lt;br /&gt;
 InternalHosts refile:/etc/opendkim/TrustedHosts&lt;br /&gt;
&lt;br /&gt;
* /etc/opendkim/KeyTable&lt;br /&gt;
&lt;br /&gt;
 default._domainkey.''yourdomain.com'' ''yourdomain.com'':default:/etc/opendkim/keys/default.private&lt;br /&gt;
&lt;br /&gt;
* /etc/opendkim/SigningTable&lt;br /&gt;
&lt;br /&gt;
 *@''yourdomain.com'' default._domainkey.''yourdomain.com''&lt;br /&gt;
&lt;br /&gt;
* /etc/opendkim/TrustedHosts&lt;br /&gt;
&lt;br /&gt;
 127.0.0.1&lt;br /&gt;
 ''host.yourdomain.com''&lt;br /&gt;
 ''yourdomain.com''&lt;br /&gt;
&lt;br /&gt;
Add the following three lines to the end of /etc/postfix/main.cf&lt;br /&gt;
&lt;br /&gt;
 smtpd_milters = inet:127.0.0.1:8891&lt;br /&gt;
 non_smtpd_milters = $smtpd_milters&lt;br /&gt;
 milter_default_action = accept&lt;br /&gt;
&lt;br /&gt;
Restart all the services&lt;br /&gt;
&lt;br /&gt;
 systemctl start opendkim&lt;br /&gt;
 systemctl enable opendkim&lt;br /&gt;
 systemctl restart postfix&lt;br /&gt;
&lt;br /&gt;
Add the contents of /etc/opendkim/keys/default.txt to the DNS for ''yourdomain.com'' and make sure that the zone has been reloaded.&lt;br /&gt;
&lt;br /&gt;
Send a test email:&lt;br /&gt;
&lt;br /&gt;
 # sendmail -fyou@yourdomain.com -t&lt;br /&gt;
 To: you@externaldomain.com&lt;br /&gt;
 From: you@yourdomain.com&lt;br /&gt;
 Subject: DKIM test with Postfix MTA&lt;br /&gt;
 &lt;br /&gt;
 Test&lt;br /&gt;
 .&lt;br /&gt;
&lt;br /&gt;
Check the maillog:&lt;br /&gt;
&lt;br /&gt;
 Oct 15 13:07:11 host opendkim[3530]: 34D25401AE: DKIM-Signature field added (s=default, d=yourdomain.com)&lt;br /&gt;
&lt;br /&gt;
Testing it:&lt;br /&gt;
&lt;br /&gt;
Try the site at http://www.appmaildev.com/en/dkim/&lt;br /&gt;
&lt;br /&gt;
== Configure Postfix to block outgoing email to all but one domain ==&lt;br /&gt;
&lt;br /&gt;
This is useful on demo systems where you don't want to be sending most email but still require the ability to send emails to a particular domain or two.&lt;br /&gt;
&lt;br /&gt;
The correct way is to use Transport Mapping. Check &amp;lt;code&amp;gt;/etc/postfix/main.cf&amp;lt;/code&amp;gt; for a transport_maps option. If there is one already, make a note of the filename in use and substitute that in the rest of these instructions. If there isn't one, add the following to main.cf&lt;br /&gt;
&lt;br /&gt;
 transport_maps = hash:/etc/postfix/transport&lt;br /&gt;
&lt;br /&gt;
CentOS7 Postfix ships with a template transport file - either replace or append:&lt;br /&gt;
&lt;br /&gt;
 yourdomain.com :&lt;br /&gt;
 localhost :&lt;br /&gt;
 * discard:&lt;br /&gt;
&lt;br /&gt;
This will allow emails to localhost or yourdomain.com but nowhere else. You'll see in /var/log/maillog the process postfix/discard instead of postfix/smtp when dropping emails. Add whatever other domains might be required to the file. If you want a bounce, you can use  something like this instead of &amp;lt;code&amp;gt;* discard:&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 * error:Outgoing mail blocked&lt;br /&gt;
&lt;br /&gt;
Rebuild the transport hash using:&lt;br /&gt;
&lt;br /&gt;
 postmap /etc/postfix/transport&lt;br /&gt;
&lt;br /&gt;
After changing the config, restart the postfix service - this is not required if you're just changing the transport map.&lt;br /&gt;
&lt;br /&gt;
 service postfix restart&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Perl&amp;diff=368</id>
		<title>Perl</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Perl&amp;diff=368"/>
				<updated>2018-10-12T14:04:26Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Mixing STDOUT and STDERR output in the right order */ generating methods&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frameworks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.catalystframework.org/calendar/2011/15 Catalyst Advent Calendar]&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
&lt;br /&gt;
DBIx::Class modules&lt;br /&gt;
&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/ResultSet.pm&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/Schema.pm&lt;br /&gt;
* http://search.cpan.org/~ironcamel/Dancer-Plugin-DBIC/lib/Dancer/Plugin/DBIC.pm&lt;br /&gt;
* http://search.cpan.org/~flora/DBIx-Class-PassphraseColumn-0.02/lib/DBIx/Class/PassphraseColumn.pm&lt;br /&gt;
&lt;br /&gt;
== Custom Perl ==&lt;br /&gt;
&lt;br /&gt;
Installing a custom version of Perl just for a single user (e.g a project) without breaking the system-wide Perl.&lt;br /&gt;
&lt;br /&gt;
Packages required:&lt;br /&gt;
&lt;br /&gt;
 gcc patch bzip2 gcc-c++ make automake&lt;br /&gt;
&lt;br /&gt;
As the unprivileged user:&lt;br /&gt;
&lt;br /&gt;
 $ curl -L https://install.perlbrew.pl | bash&lt;br /&gt;
 $ source ~/perl5/perlbrew/etc/bashrc&lt;br /&gt;
 $ perlbrew install perl-5.20.1&lt;br /&gt;
 $ perlbrew switch perl-5.20.1&lt;br /&gt;
 $ perlbrew install-cpanm&lt;br /&gt;
 $ echo 'source /home/plates/perl5/perlbrew/etc/bashrc' &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&lt;br /&gt;
After this you should be always using Perl 5.20.1 as this user (that's what the perlbrew switch does). To install modules, simply use ''cpanm'' followed by the module name.&lt;br /&gt;
&lt;br /&gt;
== Extra Perl modules for Catalyst dev ==&lt;br /&gt;
&lt;br /&gt;
After installing a custom version of Perl as above it's a good idea to install a bunch of frequently used modules if you're doing any kind of Catalyst development.&lt;br /&gt;
&lt;br /&gt;
 cpanm Catalyst::Devel DBIx::Class::TimeStamp DBIx::Class::PassphraseColumn \&lt;br /&gt;
   DBIx::Class::InflateColumn::Serializer Catalyst::Model::DBIC::Schema \&lt;br /&gt;
   Catalyst::Plugin::Authentication Catalyst::Plugin::Authorization::Roles \&lt;br /&gt;
   Catalyst::Plugin::Session Catalyst::Plugin::Session::Store::DBI \&lt;br /&gt;
   Catalyst::Plugin::Session::State::Cookie Catalyst::Plugin::StatusMessage \&lt;br /&gt;
   Catalyst::Authentication::Store::DBIx::Class Catalyst::View::TT \&lt;br /&gt;
   Catalyst::View::JSON Log::Log4perl::Catalyst DBD::mysql Email::Valid \&lt;br /&gt;
   Text::CSV_XS LWP::Protocol::https XML::Simple XML::Writer GD::Image \&lt;br /&gt;
   GD::Text FCGI::ProcManager Catalyst::View::Email::Template \&lt;br /&gt;
   Template::Plugin::DateTime HTML::Tiny Hashids Term::Size::Any Time::ParseDate&lt;br /&gt;
&lt;br /&gt;
== Accessing SQL Server from Perl ==&lt;br /&gt;
&lt;br /&gt;
Install the freetds software (both main package and devel)&lt;br /&gt;
&lt;br /&gt;
 yum install freetds freetds-devel&lt;br /&gt;
&lt;br /&gt;
Configure a server definition in the global config file, I'm not sure there's a way to avoid having to do this.&lt;br /&gt;
&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/freetds.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 [myserver]&lt;br /&gt;
   host = 192.168.1.4&lt;br /&gt;
   port = 1433&lt;br /&gt;
   tds version = 7.0&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Test the connection using the following:&lt;br /&gt;
&lt;br /&gt;
 tsql -S myserver -U myuser&lt;br /&gt;
&lt;br /&gt;
You should be prompted for a password (SQL auth, not Windows!) and hopefully after providing one, you should see a prompt &amp;lt;code&amp;gt;1)&amp;lt;/code&amp;gt; waiting for an SQL query.&lt;br /&gt;
&lt;br /&gt;
Run the following query to see the available databases.&lt;br /&gt;
&lt;br /&gt;
 SELECT name, database_id, create_date&lt;br /&gt;
 FROM sys.databases;&lt;br /&gt;
 GO&lt;br /&gt;
&lt;br /&gt;
If this didn't work, go back and check your setup.&lt;br /&gt;
&lt;br /&gt;
Install the perl module for DBD::Sybase - don't bother with the ODBC method, this way works just fine.&lt;br /&gt;
&lt;br /&gt;
 SYBASE=/usr cpanm DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
Connect using Perl and DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 use DBI;&lt;br /&gt;
 my $dbh = DBI-&amp;gt;connect(&amp;quot;DBI:Sybase:server=myserver&amp;quot;,&amp;quot;myuser&amp;quot;,&amp;quot;mypass&amp;quot;) or die $DBI::errstr;&lt;br /&gt;
 $dbh-&amp;gt;disconnect();&lt;br /&gt;
&lt;br /&gt;
If this works, you're all set.&lt;br /&gt;
&lt;br /&gt;
== DBIx::Class ==&lt;br /&gt;
&lt;br /&gt;
=== Relationships ===&lt;br /&gt;
&lt;br /&gt;
'''belongs_to''' means: a field (or fields) in THIS table is a foreign key (contains the primary key of) THAT other table.&lt;br /&gt;
&lt;br /&gt;
'''has_many''' means: there are multiple (zero or more) rows in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''has_one''' means: there ''is'' a row in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''might_have''' means: the same as '''has_one''', except its not guaranteed to be there.&lt;br /&gt;
&lt;br /&gt;
=== Cascading ===&lt;br /&gt;
&lt;br /&gt;
Attributes are required for the different relationships to disable cascading of delete/update.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;has_one&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;might_have&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 { cascade_delete =&amp;gt; 0, cascade_update =&amp;gt; 0 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;belongs_to&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 { on_delete =&amp;gt; undef, on_update =&amp;gt; undef }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;has_many&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 { cascade_delete =&amp;gt; 0 }&lt;br /&gt;
&lt;br /&gt;
=== Dates ===&lt;br /&gt;
&lt;br /&gt;
Adding a database independent way of fetching the current date/time in UTC.&lt;br /&gt;
&lt;br /&gt;
 package TestApp::Schema::ResultSet::Test;&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 &lt;br /&gt;
 use parent 'DBIx::Class::ResultSet';&lt;br /&gt;
 &lt;br /&gt;
 __PACKAGE__-&amp;gt;load_components('Helper::ResultSet::DateMethods1');&lt;br /&gt;
 &lt;br /&gt;
 1;&lt;br /&gt;
&lt;br /&gt;
and then using it, get the resultset and the first test (id = 1)&lt;br /&gt;
&lt;br /&gt;
 my $tests = $schema-&amp;gt;resultset('Test');&lt;br /&gt;
 my $test = $tests-&amp;gt;find(1);&lt;br /&gt;
&lt;br /&gt;
and to set the date&lt;br /&gt;
&lt;br /&gt;
 $test-&amp;gt;test_date( $test-&amp;gt;result_source-&amp;gt;resultset-&amp;gt;utc_now );&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 $test-&amp;gt;test_date( $tests-&amp;gt;utc_now );&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Mixing STDOUT and STDERR output in the right order ===&lt;br /&gt;
&lt;br /&gt;
STDOUT and STDERR are block buffered when there is no terminal, or line buffered when there is a terminal. This has the unfortunate side effect of making output from print/warn mess up when running a script from cron when the same script works perfectly run from the command line.&lt;br /&gt;
&lt;br /&gt;
Redirect STDERR to the same stream as STDOUT (equiv to 2&amp;gt;&amp;amp;1 in bash) - this isn't essential, but makes it easier to pipe the output through tail/mail/etc, or redirect the output to a logfile.&lt;br /&gt;
&lt;br /&gt;
 close(STDERR);&lt;br /&gt;
 open(STDERR, &amp;quot;&amp;gt;&amp;amp;STDOUT&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Make both streams non-buffering&lt;br /&gt;
&lt;br /&gt;
 select(STDERR);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
 select(STDOUT);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
&lt;br /&gt;
Alternatively, instead of the select() above, you can use IO::Handle&lt;br /&gt;
&lt;br /&gt;
 use IO::Handle;&lt;br /&gt;
 STDERR-&amp;gt;autoflush(1);&lt;br /&gt;
 STDOUT-&amp;gt;autoflush(1);&lt;br /&gt;
&lt;br /&gt;
=== Generating almost identical methods ===&lt;br /&gt;
&lt;br /&gt;
You could use Moose to do something like this but what if you want to do something other than simple getter/setter methods? This works as far as I've tested it. I'm open to alternative suggestions though!&lt;br /&gt;
&lt;br /&gt;
 BEGIN {&lt;br /&gt;
    foreach my $k (qw/name company address1 address2 area city postcode country phone email fax/) {&lt;br /&gt;
        no strict 'refs';&lt;br /&gt;
        *{&amp;quot;MyModule::$k&amp;quot;} = sub {&lt;br /&gt;
            my $self = shift;&lt;br /&gt;
            my $value = shift;&lt;br /&gt;
            if (defined $value) {&lt;br /&gt;
                $self-&amp;gt;{ $k } = $value;&lt;br /&gt;
            }&lt;br /&gt;
            return $self-&amp;gt;{ $k };&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Category:Programming]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Perl&amp;diff=367</id>
		<title>Perl</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Perl&amp;diff=367"/>
				<updated>2018-10-05T09:02:19Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Relationships */ cascading&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frameworks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.catalystframework.org/calendar/2011/15 Catalyst Advent Calendar]&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
&lt;br /&gt;
DBIx::Class modules&lt;br /&gt;
&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/ResultSet.pm&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/Schema.pm&lt;br /&gt;
* http://search.cpan.org/~ironcamel/Dancer-Plugin-DBIC/lib/Dancer/Plugin/DBIC.pm&lt;br /&gt;
* http://search.cpan.org/~flora/DBIx-Class-PassphraseColumn-0.02/lib/DBIx/Class/PassphraseColumn.pm&lt;br /&gt;
&lt;br /&gt;
== Custom Perl ==&lt;br /&gt;
&lt;br /&gt;
Installing a custom version of Perl just for a single user (e.g a project) without breaking the system-wide Perl.&lt;br /&gt;
&lt;br /&gt;
Packages required:&lt;br /&gt;
&lt;br /&gt;
 gcc patch bzip2 gcc-c++ make automake&lt;br /&gt;
&lt;br /&gt;
As the unprivileged user:&lt;br /&gt;
&lt;br /&gt;
 $ curl -L https://install.perlbrew.pl | bash&lt;br /&gt;
 $ source ~/perl5/perlbrew/etc/bashrc&lt;br /&gt;
 $ perlbrew install perl-5.20.1&lt;br /&gt;
 $ perlbrew switch perl-5.20.1&lt;br /&gt;
 $ perlbrew install-cpanm&lt;br /&gt;
 $ echo 'source /home/plates/perl5/perlbrew/etc/bashrc' &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&lt;br /&gt;
After this you should be always using Perl 5.20.1 as this user (that's what the perlbrew switch does). To install modules, simply use ''cpanm'' followed by the module name.&lt;br /&gt;
&lt;br /&gt;
== Extra Perl modules for Catalyst dev ==&lt;br /&gt;
&lt;br /&gt;
After installing a custom version of Perl as above it's a good idea to install a bunch of frequently used modules if you're doing any kind of Catalyst development.&lt;br /&gt;
&lt;br /&gt;
 cpanm Catalyst::Devel DBIx::Class::TimeStamp DBIx::Class::PassphraseColumn \&lt;br /&gt;
   DBIx::Class::InflateColumn::Serializer Catalyst::Model::DBIC::Schema \&lt;br /&gt;
   Catalyst::Plugin::Authentication Catalyst::Plugin::Authorization::Roles \&lt;br /&gt;
   Catalyst::Plugin::Session Catalyst::Plugin::Session::Store::DBI \&lt;br /&gt;
   Catalyst::Plugin::Session::State::Cookie Catalyst::Plugin::StatusMessage \&lt;br /&gt;
   Catalyst::Authentication::Store::DBIx::Class Catalyst::View::TT \&lt;br /&gt;
   Catalyst::View::JSON Log::Log4perl::Catalyst DBD::mysql Email::Valid \&lt;br /&gt;
   Text::CSV_XS LWP::Protocol::https XML::Simple XML::Writer GD::Image \&lt;br /&gt;
   GD::Text FCGI::ProcManager Catalyst::View::Email::Template \&lt;br /&gt;
   Template::Plugin::DateTime HTML::Tiny Hashids Term::Size::Any Time::ParseDate&lt;br /&gt;
&lt;br /&gt;
== Accessing SQL Server from Perl ==&lt;br /&gt;
&lt;br /&gt;
Install the freetds software (both main package and devel)&lt;br /&gt;
&lt;br /&gt;
 yum install freetds freetds-devel&lt;br /&gt;
&lt;br /&gt;
Configure a server definition in the global config file, I'm not sure there's a way to avoid having to do this.&lt;br /&gt;
&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/freetds.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 [myserver]&lt;br /&gt;
   host = 192.168.1.4&lt;br /&gt;
   port = 1433&lt;br /&gt;
   tds version = 7.0&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Test the connection using the following:&lt;br /&gt;
&lt;br /&gt;
 tsql -S myserver -U myuser&lt;br /&gt;
&lt;br /&gt;
You should be prompted for a password (SQL auth, not Windows!) and hopefully after providing one, you should see a prompt &amp;lt;code&amp;gt;1)&amp;lt;/code&amp;gt; waiting for an SQL query.&lt;br /&gt;
&lt;br /&gt;
Run the following query to see the available databases.&lt;br /&gt;
&lt;br /&gt;
 SELECT name, database_id, create_date&lt;br /&gt;
 FROM sys.databases;&lt;br /&gt;
 GO&lt;br /&gt;
&lt;br /&gt;
If this didn't work, go back and check your setup.&lt;br /&gt;
&lt;br /&gt;
Install the perl module for DBD::Sybase - don't bother with the ODBC method, this way works just fine.&lt;br /&gt;
&lt;br /&gt;
 SYBASE=/usr cpanm DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
Connect using Perl and DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 use DBI;&lt;br /&gt;
 my $dbh = DBI-&amp;gt;connect(&amp;quot;DBI:Sybase:server=myserver&amp;quot;,&amp;quot;myuser&amp;quot;,&amp;quot;mypass&amp;quot;) or die $DBI::errstr;&lt;br /&gt;
 $dbh-&amp;gt;disconnect();&lt;br /&gt;
&lt;br /&gt;
If this works, you're all set.&lt;br /&gt;
&lt;br /&gt;
== DBIx::Class ==&lt;br /&gt;
&lt;br /&gt;
=== Relationships ===&lt;br /&gt;
&lt;br /&gt;
'''belongs_to''' means: a field (or fields) in THIS table is a foreign key (contains the primary key of) THAT other table.&lt;br /&gt;
&lt;br /&gt;
'''has_many''' means: there are multiple (zero or more) rows in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''has_one''' means: there ''is'' a row in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''might_have''' means: the same as '''has_one''', except its not guaranteed to be there.&lt;br /&gt;
&lt;br /&gt;
=== Cascading ===&lt;br /&gt;
&lt;br /&gt;
Attributes are required for the different relationships to disable cascading of delete/update.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;has_one&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;might_have&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 { cascade_delete =&amp;gt; 0, cascade_update =&amp;gt; 0 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;belongs_to&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 { on_delete =&amp;gt; undef, on_update =&amp;gt; undef }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;has_many&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 { cascade_delete =&amp;gt; 0 }&lt;br /&gt;
&lt;br /&gt;
=== Dates ===&lt;br /&gt;
&lt;br /&gt;
Adding a database independent way of fetching the current date/time in UTC.&lt;br /&gt;
&lt;br /&gt;
 package TestApp::Schema::ResultSet::Test;&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 &lt;br /&gt;
 use parent 'DBIx::Class::ResultSet';&lt;br /&gt;
 &lt;br /&gt;
 __PACKAGE__-&amp;gt;load_components('Helper::ResultSet::DateMethods1');&lt;br /&gt;
 &lt;br /&gt;
 1;&lt;br /&gt;
&lt;br /&gt;
and then using it, get the resultset and the first test (id = 1)&lt;br /&gt;
&lt;br /&gt;
 my $tests = $schema-&amp;gt;resultset('Test');&lt;br /&gt;
 my $test = $tests-&amp;gt;find(1);&lt;br /&gt;
&lt;br /&gt;
and to set the date&lt;br /&gt;
&lt;br /&gt;
 $test-&amp;gt;test_date( $test-&amp;gt;result_source-&amp;gt;resultset-&amp;gt;utc_now );&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 $test-&amp;gt;test_date( $tests-&amp;gt;utc_now );&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Mixing STDOUT and STDERR output in the right order ===&lt;br /&gt;
&lt;br /&gt;
STDOUT and STDERR are block buffered when there is no terminal, or line buffered when there is a terminal. This has the unfortunate side effect of making output from print/warn mess up when running a script from cron when the same script works perfectly run from the command line.&lt;br /&gt;
&lt;br /&gt;
Redirect STDERR to the same stream as STDOUT (equiv to 2&amp;gt;&amp;amp;1 in bash) - this isn't essential, but makes it easier to pipe the output through tail/mail/etc, or redirect the output to a logfile.&lt;br /&gt;
&lt;br /&gt;
 close(STDERR);&lt;br /&gt;
 open(STDERR, &amp;quot;&amp;gt;&amp;amp;STDOUT&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Make both streams non-buffering&lt;br /&gt;
&lt;br /&gt;
 select(STDERR);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
 select(STDOUT);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
&lt;br /&gt;
Alternatively, instead of the select() above, you can use IO::Handle&lt;br /&gt;
&lt;br /&gt;
 use IO::Handle;&lt;br /&gt;
 STDERR-&amp;gt;autoflush(1);&lt;br /&gt;
 STDOUT-&amp;gt;autoflush(1);&lt;br /&gt;
&lt;br /&gt;
[[Category:Programming]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Git&amp;diff=366</id>
		<title>Git</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Git&amp;diff=366"/>
				<updated>2018-10-02T11:30:50Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Graphical view of commits */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellpadding=10 align=right&lt;br /&gt;
| __TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Writing Good Commit Messages ==&lt;br /&gt;
&lt;br /&gt;
There are just two rules for writing good commit messages.&lt;br /&gt;
&lt;br /&gt;
# '''DO NOT''' just put &amp;quot;bugfix&amp;quot; or &amp;quot;updated this&amp;quot;&lt;br /&gt;
# '''Limit the commit message to approx 50 characters'''&lt;br /&gt;
&lt;br /&gt;
Unless it is immediately obvious what was changed from the output of ''git diff somepath/somefile'' - it is always better to put things like &amp;quot;Bugfix - picked the wrong something for featureX&amp;quot; or &amp;quot;Updated image to reflect new pricing&amp;quot; to prevent someone else from having to stare at the diff output to work out what was changed.&lt;br /&gt;
&lt;br /&gt;
The 50 character limit is because some of the git commands use the first line of the log message and the output will look a bit messed up if it's too long. An example of this is ''git log --oneline''&lt;br /&gt;
&lt;br /&gt;
If you can't fit everything in about 50 characters or if the commit is particularly complicated, do not use the ''-m'' option with ''git commit''. You will be dropped into your editor of choice (most likely vi) and then can make the first line a 50 character summary of the commit, add a blank line and then any other comments that are required.&lt;br /&gt;
&lt;br /&gt;
== Configuration of git ==&lt;br /&gt;
&lt;br /&gt;
The following commands should all be run from the shell.&lt;br /&gt;
&lt;br /&gt;
 git config --global user.name &amp;quot;Simon Amor&amp;quot;&lt;br /&gt;
 git config --global user.email simon@leaky.org&lt;br /&gt;
 git config --global color.diff auto&lt;br /&gt;
 git config --global color.status auto&lt;br /&gt;
 git config --global color.branch auto&lt;br /&gt;
 git config --global diff.renamelimit 40960&lt;br /&gt;
&lt;br /&gt;
Recent versions of git will complain about the way git-push is going to work, to stop this it's recommended you use the following command. If you prefer the original behaviour for matching branches, use 'matching' instead of 'simple'&lt;br /&gt;
&lt;br /&gt;
 git config --global push.default simple&lt;br /&gt;
&lt;br /&gt;
* '''matching''' means git push will push all your local branches to the ones with the same name on the remote. This makes it easy to accidentally push a branch you didn't intend to.&lt;br /&gt;
* '''simple''' means git push will push only the current branch to the one that git pull would pull from, and also checks that their names match. This is a more intuitive behavior, which is why the default is getting changed to this.&lt;br /&gt;
&lt;br /&gt;
If you prefer long lines to be wrapped within less, the following will fix this.&lt;br /&gt;
&lt;br /&gt;
 git config --global core.pager 'less -+$LESS -iR'&lt;br /&gt;
&lt;br /&gt;
Other options you may with to add to -iR include -eFX (-e and -F are similar and relate to exiting on eof, -X doesn't initialise the terminal)&lt;br /&gt;
&lt;br /&gt;
== Showing all branches ==&lt;br /&gt;
&lt;br /&gt;
Because the repository is a clone of a remote repository, you need to specify -r to the ''git branch'' command to show remote branches as well.&lt;br /&gt;
&lt;br /&gt;
 git branch -r&lt;br /&gt;
&lt;br /&gt;
== Showing remote branches and local branches ==&lt;br /&gt;
&lt;br /&gt;
 git branch -a&lt;br /&gt;
&lt;br /&gt;
== Comparing branches ==&lt;br /&gt;
&lt;br /&gt;
git log has a number of options but the commonly used ones are:&lt;br /&gt;
* -p will include the patch for the commit&lt;br /&gt;
* --pretty=oneline returns just the sha1 and the first line of the commit message.&lt;br /&gt;
&lt;br /&gt;
To find all the commits that are in one or other branch, but not in both (exclude the common ancestors)&lt;br /&gt;
&lt;br /&gt;
 git log master...working&lt;br /&gt;
&lt;br /&gt;
This will show anything new that was added to ''master'' as well as anything new added to ''working''&lt;br /&gt;
&lt;br /&gt;
 git log master..working&lt;br /&gt;
&lt;br /&gt;
This will show anything new added to ''working'' that wasn't already in ''master''&lt;br /&gt;
&lt;br /&gt;
 git log working..master&lt;br /&gt;
&lt;br /&gt;
This will show anything new added to ''master'' that wasn't already in ''working''&lt;br /&gt;
&lt;br /&gt;
== View changes in Staged files ==&lt;br /&gt;
&lt;br /&gt;
Shows differences between HEAD and staged (added) file&lt;br /&gt;
&lt;br /&gt;
 git add myfile.txt&lt;br /&gt;
 git diff --cached myfile.txt&lt;br /&gt;
&lt;br /&gt;
== Merging a branch ==&lt;br /&gt;
&lt;br /&gt;
To merge branchname into the current branch, use ''git merge branchname'' - this will replay all the changes in the branch onto the current and hopefully not cause any conflicts.&lt;br /&gt;
&lt;br /&gt;
 git merge branchname&lt;br /&gt;
&lt;br /&gt;
== Deleting a merged branch ==&lt;br /&gt;
&lt;br /&gt;
Be very careful! To remove a branch from your local repository, simply use the following to list the branches&lt;br /&gt;
&lt;br /&gt;
 git branch&lt;br /&gt;
&lt;br /&gt;
and to remove the branch called ''branchname''&lt;br /&gt;
&lt;br /&gt;
 git branch -d branchname&lt;br /&gt;
&lt;br /&gt;
If it has not been merged into another branch, you might get a warning that it contains unmerged content.&lt;br /&gt;
&lt;br /&gt;
In order to remove the branch from your remote repository, you need to specifically push an empty repository to that branch.&lt;br /&gt;
&lt;br /&gt;
 git push origin :branchname&lt;br /&gt;
&lt;br /&gt;
Once it's removed from both your local and remote repositories, it most likely cannot be retrieved unless someone else fetched your remote repository and still has a copy of it!&lt;br /&gt;
&lt;br /&gt;
== Viewing a previous revision of a file ==&lt;br /&gt;
&lt;br /&gt;
To view the content of a previous revision of a file without checking out that revision, use '''git show'''&lt;br /&gt;
&lt;br /&gt;
 git show dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/mytestscript.pl&lt;br /&gt;
&lt;br /&gt;
You can also redirect the output to a file, for example if you want to revert an image rather than text.&lt;br /&gt;
&lt;br /&gt;
== Viewing the directory listing for a previous revision ==&lt;br /&gt;
&lt;br /&gt;
It may be the case that after a particular revision, some files have been removed but you want to know what files were present (maybe to use git show with them to view the content).&lt;br /&gt;
&lt;br /&gt;
To view the top-level directory of the repository&lt;br /&gt;
&lt;br /&gt;
 git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b&lt;br /&gt;
&lt;br /&gt;
To view the contents of a specific path&lt;br /&gt;
&lt;br /&gt;
 git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/somedir/&lt;br /&gt;
&lt;br /&gt;
The files listed can be viewed either using git show ''revision'':''path'' or git show ''blob-id'' where the blob id is the third column in the output from git ls-tree.&lt;br /&gt;
&lt;br /&gt;
== View creation dates of branches ==&lt;br /&gt;
&lt;br /&gt;
 git for-each-ref --sort='-authordate:iso8601' \&lt;br /&gt;
   --format=' %(authordate:iso8601)%09%(refname)' refs/heads&lt;br /&gt;
&lt;br /&gt;
== Add specific lines ==&lt;br /&gt;
&lt;br /&gt;
 git add -e filepath/filename&lt;br /&gt;
&lt;br /&gt;
This will open up the differences of the file into vi, remove all changes that you don't want applied to this patch then :wq to save and apply the new add.&lt;br /&gt;
To cancel the patch and not apply any changes delete all lines in vi and :wq&lt;br /&gt;
&lt;br /&gt;
An alternative to this, if the hunks you wish to commit are separate, is to use&lt;br /&gt;
&lt;br /&gt;
 git add -p filepath/filename&lt;br /&gt;
&lt;br /&gt;
This prompts you for each hunk whether to stage it (y), or skip it (n) - there are other options but generally these two are the only ones you'll need.&lt;br /&gt;
&lt;br /&gt;
== Fix half-updated dev box ==&lt;br /&gt;
&lt;br /&gt;
 git stash save&lt;br /&gt;
 git pull&lt;br /&gt;
 git stash apply &amp;lt;stashname&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Stash only specific files ==&lt;br /&gt;
&lt;br /&gt;
Stash usually stashes all changes, to stash only certain files, git add all the files that you don't want stashed, then run&lt;br /&gt;
&lt;br /&gt;
 git stash --keep-index&lt;br /&gt;
&lt;br /&gt;
== View log for a file that has since been deleted ==&lt;br /&gt;
&lt;br /&gt;
 git log -p --follow -- full/file/path.txt&lt;br /&gt;
&lt;br /&gt;
== Viewing the diff ignoring whitespace changes ==&lt;br /&gt;
&lt;br /&gt;
 git diff --ignore-space-at-eol -b -w simon/mytestscript.pl&lt;br /&gt;
&lt;br /&gt;
== Graphical view of commits ==&lt;br /&gt;
&lt;br /&gt;
A semi-graphical view of how the current branch has branched and merged.&lt;br /&gt;
&lt;br /&gt;
 git log --graph --oneline&lt;br /&gt;
&lt;br /&gt;
== Rewrite author of all commits ==&lt;br /&gt;
&lt;br /&gt;
Committed an entire repository with the wrong email/name for the committer? Run the following to reset everything. '''Be careful!'''&lt;br /&gt;
&lt;br /&gt;
 git filter-branch -f --env-filter \&lt;br /&gt;
  &amp;quot;GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \&lt;br /&gt;
  GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';&amp;quot; HEAD&lt;br /&gt;
&lt;br /&gt;
Output (for a repository with only 4 commits):&lt;br /&gt;
&lt;br /&gt;
 Rewrite e996a36094ba2a516dcf6bebc115f7ac25b2da6a (1/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 511aef3d14e92dbc2847934cf6313fd328aaf33d (2/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 0d6b36c9c27568161e4b4a47b2fdeefc98742379 (3/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Rewrite 65b29f4418d773704e7055399c55959e45953108 (4/4) (0 seconds passed, remaining 0 predicted)&lt;br /&gt;
 Ref 'refs/heads/master' was rewritten&lt;br /&gt;
&lt;br /&gt;
== Storing the .git directory outside the work tree ==&lt;br /&gt;
&lt;br /&gt;
* content copied from http://stackoverflow.com/questions/505467/can-i-store-the-git-folder-outside-the-files-i-want-tracked&lt;br /&gt;
&lt;br /&gt;
You just need to ensure that the repository knows where the work tree is and vice versa.&lt;br /&gt;
&lt;br /&gt;
To let the repository know where the work tree is, set the configuration value core.worktree. To let the work tree know where it's git directory is, add a file named .git (not a folder!) and add a line like&lt;br /&gt;
&lt;br /&gt;
 gitdir: /path/to/repo.git&lt;br /&gt;
&lt;br /&gt;
Since git 1.7.5 the init command learned an extra option for this. You can initialize a new separate repository with&lt;br /&gt;
&lt;br /&gt;
 git --separate-git-dir /path/to/repo.git init&lt;br /&gt;
&lt;br /&gt;
This will initialize the git repository in the separate directory and add the .git file in the current directory, which is the working directory of the new repository. (Note: tried on 1.8.3 and it didn't recognise the option)&lt;br /&gt;
&lt;br /&gt;
Previously to 1.7.5 you had to use slightly different parameters and add the .git file yourself. To initialize a separate repository the following command links the work-tree with the repository:&lt;br /&gt;
&lt;br /&gt;
 git --git-dir=/path/to/repo.git --work-tree=. init &amp;amp;&amp;amp; echo &amp;quot;gitdir: /path/to/repo.git&amp;quot; &amp;gt; .git&lt;br /&gt;
&lt;br /&gt;
Your current directory will be the working tree and git will use the repository at /path/to/repo.git. The init command will automatically set the core.worktree value as specified with the --git-dir parameter.&lt;br /&gt;
&lt;br /&gt;
== Updating git ==&lt;br /&gt;
&lt;br /&gt;
To update CentOS7 to the latest version 2 git, use the IUS repository.&lt;br /&gt;
&lt;br /&gt;
Get the package url from https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/repoview/git2u.html and use it in the following command:&lt;br /&gt;
&lt;br /&gt;
 # yum install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/git2u-2.11.1-1.ius.centos7.x86_64.rpm&lt;br /&gt;
&lt;br /&gt;
If you already have the default version of git installed, you'll need to remove it first with this command:&lt;br /&gt;
&lt;br /&gt;
 # yum remove git perl-Git&lt;br /&gt;
&lt;br /&gt;
== Aliases ==&lt;br /&gt;
&lt;br /&gt;
Edit ~/.gitconfig and add:&lt;br /&gt;
&lt;br /&gt;
 [alias]&lt;br /&gt;
    lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset'&lt;br /&gt;
&lt;br /&gt;
Prevent accidental double (or more) git's from causing errors. e.g 'git git status' =&amp;gt; 'git status'&lt;br /&gt;
&lt;br /&gt;
 git config --global alias.git '!exec git'&lt;br /&gt;
&lt;br /&gt;
(or add this to your .gitconfig)&lt;br /&gt;
&lt;br /&gt;
 [alias]&lt;br /&gt;
   git = !exec git&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Perl&amp;diff=365</id>
		<title>Perl</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Perl&amp;diff=365"/>
				<updated>2018-10-02T11:27:50Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* DBIx::Class */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frameworks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.catalystframework.org/calendar/2011/15 Catalyst Advent Calendar]&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
&lt;br /&gt;
DBIx::Class modules&lt;br /&gt;
&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/ResultSet.pm&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/Schema.pm&lt;br /&gt;
* http://search.cpan.org/~ironcamel/Dancer-Plugin-DBIC/lib/Dancer/Plugin/DBIC.pm&lt;br /&gt;
* http://search.cpan.org/~flora/DBIx-Class-PassphraseColumn-0.02/lib/DBIx/Class/PassphraseColumn.pm&lt;br /&gt;
&lt;br /&gt;
== Custom Perl ==&lt;br /&gt;
&lt;br /&gt;
Installing a custom version of Perl just for a single user (e.g a project) without breaking the system-wide Perl.&lt;br /&gt;
&lt;br /&gt;
Packages required:&lt;br /&gt;
&lt;br /&gt;
 gcc patch bzip2 gcc-c++ make automake&lt;br /&gt;
&lt;br /&gt;
As the unprivileged user:&lt;br /&gt;
&lt;br /&gt;
 $ curl -L https://install.perlbrew.pl | bash&lt;br /&gt;
 $ source ~/perl5/perlbrew/etc/bashrc&lt;br /&gt;
 $ perlbrew install perl-5.20.1&lt;br /&gt;
 $ perlbrew switch perl-5.20.1&lt;br /&gt;
 $ perlbrew install-cpanm&lt;br /&gt;
 $ echo 'source /home/plates/perl5/perlbrew/etc/bashrc' &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&lt;br /&gt;
After this you should be always using Perl 5.20.1 as this user (that's what the perlbrew switch does). To install modules, simply use ''cpanm'' followed by the module name.&lt;br /&gt;
&lt;br /&gt;
== Extra Perl modules for Catalyst dev ==&lt;br /&gt;
&lt;br /&gt;
After installing a custom version of Perl as above it's a good idea to install a bunch of frequently used modules if you're doing any kind of Catalyst development.&lt;br /&gt;
&lt;br /&gt;
 cpanm Catalyst::Devel DBIx::Class::TimeStamp DBIx::Class::PassphraseColumn \&lt;br /&gt;
   DBIx::Class::InflateColumn::Serializer Catalyst::Model::DBIC::Schema \&lt;br /&gt;
   Catalyst::Plugin::Authentication Catalyst::Plugin::Authorization::Roles \&lt;br /&gt;
   Catalyst::Plugin::Session Catalyst::Plugin::Session::Store::DBI \&lt;br /&gt;
   Catalyst::Plugin::Session::State::Cookie Catalyst::Plugin::StatusMessage \&lt;br /&gt;
   Catalyst::Authentication::Store::DBIx::Class Catalyst::View::TT \&lt;br /&gt;
   Catalyst::View::JSON Log::Log4perl::Catalyst DBD::mysql Email::Valid \&lt;br /&gt;
   Text::CSV_XS LWP::Protocol::https XML::Simple XML::Writer GD::Image \&lt;br /&gt;
   GD::Text FCGI::ProcManager Catalyst::View::Email::Template \&lt;br /&gt;
   Template::Plugin::DateTime HTML::Tiny Hashids Term::Size::Any Time::ParseDate&lt;br /&gt;
&lt;br /&gt;
== Accessing SQL Server from Perl ==&lt;br /&gt;
&lt;br /&gt;
Install the freetds software (both main package and devel)&lt;br /&gt;
&lt;br /&gt;
 yum install freetds freetds-devel&lt;br /&gt;
&lt;br /&gt;
Configure a server definition in the global config file, I'm not sure there's a way to avoid having to do this.&lt;br /&gt;
&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/freetds.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 [myserver]&lt;br /&gt;
   host = 192.168.1.4&lt;br /&gt;
   port = 1433&lt;br /&gt;
   tds version = 7.0&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Test the connection using the following:&lt;br /&gt;
&lt;br /&gt;
 tsql -S myserver -U myuser&lt;br /&gt;
&lt;br /&gt;
You should be prompted for a password (SQL auth, not Windows!) and hopefully after providing one, you should see a prompt &amp;lt;code&amp;gt;1)&amp;lt;/code&amp;gt; waiting for an SQL query.&lt;br /&gt;
&lt;br /&gt;
Run the following query to see the available databases.&lt;br /&gt;
&lt;br /&gt;
 SELECT name, database_id, create_date&lt;br /&gt;
 FROM sys.databases;&lt;br /&gt;
 GO&lt;br /&gt;
&lt;br /&gt;
If this didn't work, go back and check your setup.&lt;br /&gt;
&lt;br /&gt;
Install the perl module for DBD::Sybase - don't bother with the ODBC method, this way works just fine.&lt;br /&gt;
&lt;br /&gt;
 SYBASE=/usr cpanm DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
Connect using Perl and DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 use DBI;&lt;br /&gt;
 my $dbh = DBI-&amp;gt;connect(&amp;quot;DBI:Sybase:server=myserver&amp;quot;,&amp;quot;myuser&amp;quot;,&amp;quot;mypass&amp;quot;) or die $DBI::errstr;&lt;br /&gt;
 $dbh-&amp;gt;disconnect();&lt;br /&gt;
&lt;br /&gt;
If this works, you're all set.&lt;br /&gt;
&lt;br /&gt;
== DBIx::Class ==&lt;br /&gt;
&lt;br /&gt;
=== Relationships ===&lt;br /&gt;
&lt;br /&gt;
'''belongs_to''' means: a field (or fields) in THIS table is a foreign key (contains the primary key of) THAT other table.&lt;br /&gt;
&lt;br /&gt;
'''has_many''' means: there are multiple (zero or more) rows in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''has_one''' means: there ''is'' a row in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''might_have''' means: the same as '''has_one''', except its not guaranteed to be there.&lt;br /&gt;
&lt;br /&gt;
=== Dates ===&lt;br /&gt;
&lt;br /&gt;
Adding a database independent way of fetching the current date/time in UTC.&lt;br /&gt;
&lt;br /&gt;
 package TestApp::Schema::ResultSet::Test;&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
 &lt;br /&gt;
 use parent 'DBIx::Class::ResultSet';&lt;br /&gt;
 &lt;br /&gt;
 __PACKAGE__-&amp;gt;load_components('Helper::ResultSet::DateMethods1');&lt;br /&gt;
 &lt;br /&gt;
 1;&lt;br /&gt;
&lt;br /&gt;
and then using it, get the resultset and the first test (id = 1)&lt;br /&gt;
&lt;br /&gt;
 my $tests = $schema-&amp;gt;resultset('Test');&lt;br /&gt;
 my $test = $tests-&amp;gt;find(1);&lt;br /&gt;
&lt;br /&gt;
and to set the date&lt;br /&gt;
&lt;br /&gt;
 $test-&amp;gt;test_date( $test-&amp;gt;result_source-&amp;gt;resultset-&amp;gt;utc_now );&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 $test-&amp;gt;test_date( $tests-&amp;gt;utc_now );&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Mixing STDOUT and STDERR output in the right order ===&lt;br /&gt;
&lt;br /&gt;
STDOUT and STDERR are block buffered when there is no terminal, or line buffered when there is a terminal. This has the unfortunate side effect of making output from print/warn mess up when running a script from cron when the same script works perfectly run from the command line.&lt;br /&gt;
&lt;br /&gt;
Redirect STDERR to the same stream as STDOUT (equiv to 2&amp;gt;&amp;amp;1 in bash) - this isn't essential, but makes it easier to pipe the output through tail/mail/etc, or redirect the output to a logfile.&lt;br /&gt;
&lt;br /&gt;
 close(STDERR);&lt;br /&gt;
 open(STDERR, &amp;quot;&amp;gt;&amp;amp;STDOUT&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Make both streams non-buffering&lt;br /&gt;
&lt;br /&gt;
 select(STDERR);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
 select(STDOUT);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
&lt;br /&gt;
Alternatively, instead of the select() above, you can use IO::Handle&lt;br /&gt;
&lt;br /&gt;
 use IO::Handle;&lt;br /&gt;
 STDERR-&amp;gt;autoflush(1);&lt;br /&gt;
 STDOUT-&amp;gt;autoflush(1);&lt;br /&gt;
&lt;br /&gt;
[[Category:Programming]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Perl&amp;diff=364</id>
		<title>Perl</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Perl&amp;diff=364"/>
				<updated>2018-10-02T10:59:16Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: Added to programming category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frameworks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.catalystframework.org/calendar/2011/15 Catalyst Advent Calendar]&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
&lt;br /&gt;
DBIx::Class modules&lt;br /&gt;
&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/ResultSet.pm&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/Schema.pm&lt;br /&gt;
* http://search.cpan.org/~ironcamel/Dancer-Plugin-DBIC/lib/Dancer/Plugin/DBIC.pm&lt;br /&gt;
* http://search.cpan.org/~flora/DBIx-Class-PassphraseColumn-0.02/lib/DBIx/Class/PassphraseColumn.pm&lt;br /&gt;
&lt;br /&gt;
== Custom Perl ==&lt;br /&gt;
&lt;br /&gt;
Installing a custom version of Perl just for a single user (e.g a project) without breaking the system-wide Perl.&lt;br /&gt;
&lt;br /&gt;
Packages required:&lt;br /&gt;
&lt;br /&gt;
 gcc patch bzip2 gcc-c++ make automake&lt;br /&gt;
&lt;br /&gt;
As the unprivileged user:&lt;br /&gt;
&lt;br /&gt;
 $ curl -L https://install.perlbrew.pl | bash&lt;br /&gt;
 $ source ~/perl5/perlbrew/etc/bashrc&lt;br /&gt;
 $ perlbrew install perl-5.20.1&lt;br /&gt;
 $ perlbrew switch perl-5.20.1&lt;br /&gt;
 $ perlbrew install-cpanm&lt;br /&gt;
 $ echo 'source /home/plates/perl5/perlbrew/etc/bashrc' &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&lt;br /&gt;
After this you should be always using Perl 5.20.1 as this user (that's what the perlbrew switch does). To install modules, simply use ''cpanm'' followed by the module name.&lt;br /&gt;
&lt;br /&gt;
== Extra Perl modules for Catalyst dev ==&lt;br /&gt;
&lt;br /&gt;
After installing a custom version of Perl as above it's a good idea to install a bunch of frequently used modules if you're doing any kind of Catalyst development.&lt;br /&gt;
&lt;br /&gt;
 cpanm Catalyst::Devel DBIx::Class::TimeStamp DBIx::Class::PassphraseColumn \&lt;br /&gt;
   DBIx::Class::InflateColumn::Serializer Catalyst::Model::DBIC::Schema \&lt;br /&gt;
   Catalyst::Plugin::Authentication Catalyst::Plugin::Authorization::Roles \&lt;br /&gt;
   Catalyst::Plugin::Session Catalyst::Plugin::Session::Store::DBI \&lt;br /&gt;
   Catalyst::Plugin::Session::State::Cookie Catalyst::Plugin::StatusMessage \&lt;br /&gt;
   Catalyst::Authentication::Store::DBIx::Class Catalyst::View::TT \&lt;br /&gt;
   Catalyst::View::JSON Log::Log4perl::Catalyst DBD::mysql Email::Valid \&lt;br /&gt;
   Text::CSV_XS LWP::Protocol::https XML::Simple XML::Writer GD::Image \&lt;br /&gt;
   GD::Text FCGI::ProcManager Catalyst::View::Email::Template \&lt;br /&gt;
   Template::Plugin::DateTime HTML::Tiny Hashids Term::Size::Any Time::ParseDate&lt;br /&gt;
&lt;br /&gt;
== Accessing SQL Server from Perl ==&lt;br /&gt;
&lt;br /&gt;
Install the freetds software (both main package and devel)&lt;br /&gt;
&lt;br /&gt;
 yum install freetds freetds-devel&lt;br /&gt;
&lt;br /&gt;
Configure a server definition in the global config file, I'm not sure there's a way to avoid having to do this.&lt;br /&gt;
&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/freetds.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 [myserver]&lt;br /&gt;
   host = 192.168.1.4&lt;br /&gt;
   port = 1433&lt;br /&gt;
   tds version = 7.0&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Test the connection using the following:&lt;br /&gt;
&lt;br /&gt;
 tsql -S myserver -U myuser&lt;br /&gt;
&lt;br /&gt;
You should be prompted for a password (SQL auth, not Windows!) and hopefully after providing one, you should see a prompt &amp;lt;code&amp;gt;1)&amp;lt;/code&amp;gt; waiting for an SQL query.&lt;br /&gt;
&lt;br /&gt;
Run the following query to see the available databases.&lt;br /&gt;
&lt;br /&gt;
 SELECT name, database_id, create_date&lt;br /&gt;
 FROM sys.databases;&lt;br /&gt;
 GO&lt;br /&gt;
&lt;br /&gt;
If this didn't work, go back and check your setup.&lt;br /&gt;
&lt;br /&gt;
Install the perl module for DBD::Sybase - don't bother with the ODBC method, this way works just fine.&lt;br /&gt;
&lt;br /&gt;
 SYBASE=/usr cpanm DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
Connect using Perl and DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 use DBI;&lt;br /&gt;
 my $dbh = DBI-&amp;gt;connect(&amp;quot;DBI:Sybase:server=myserver&amp;quot;,&amp;quot;myuser&amp;quot;,&amp;quot;mypass&amp;quot;) or die $DBI::errstr;&lt;br /&gt;
 $dbh-&amp;gt;disconnect();&lt;br /&gt;
&lt;br /&gt;
If this works, you're all set.&lt;br /&gt;
&lt;br /&gt;
== DBIx::Class ==&lt;br /&gt;
&lt;br /&gt;
=== Relationships ===&lt;br /&gt;
&lt;br /&gt;
'''belongs_to''' means: a field (or fields) in THIS table is a foreign key (contains the primary key of) THAT other table.&lt;br /&gt;
&lt;br /&gt;
'''has_many''' means: there are multiple (zero or more) rows in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''has_one''' means: there ''is'' a row in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''might_have''' means: the same as '''has_one''', except its not guaranteed to be there.&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Mixing STDOUT and STDERR output in the right order ===&lt;br /&gt;
&lt;br /&gt;
STDOUT and STDERR are block buffered when there is no terminal, or line buffered when there is a terminal. This has the unfortunate side effect of making output from print/warn mess up when running a script from cron when the same script works perfectly run from the command line.&lt;br /&gt;
&lt;br /&gt;
Redirect STDERR to the same stream as STDOUT (equiv to 2&amp;gt;&amp;amp;1 in bash) - this isn't essential, but makes it easier to pipe the output through tail/mail/etc, or redirect the output to a logfile.&lt;br /&gt;
&lt;br /&gt;
 close(STDERR);&lt;br /&gt;
 open(STDERR, &amp;quot;&amp;gt;&amp;amp;STDOUT&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Make both streams non-buffering&lt;br /&gt;
&lt;br /&gt;
 select(STDERR);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
 select(STDOUT);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
&lt;br /&gt;
Alternatively, instead of the select() above, you can use IO::Handle&lt;br /&gt;
&lt;br /&gt;
 use IO::Handle;&lt;br /&gt;
 STDERR-&amp;gt;autoflush(1);&lt;br /&gt;
 STDOUT-&amp;gt;autoflush(1);&lt;br /&gt;
&lt;br /&gt;
[[Category:Programming]]&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Perl&amp;diff=363</id>
		<title>Perl</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Perl&amp;diff=363"/>
				<updated>2018-10-01T08:41:15Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Accessing SQL Server from Perl */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frameworks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.catalystframework.org/calendar/2011/15 Catalyst Advent Calendar]&lt;br /&gt;
&lt;br /&gt;
== Modules ==&lt;br /&gt;
&lt;br /&gt;
DBIx::Class modules&lt;br /&gt;
&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/ResultSet.pm&lt;br /&gt;
* http://search.cpan.org/~frew/DBIx-Class/lib/DBIx/Class/Schema.pm&lt;br /&gt;
* http://search.cpan.org/~ironcamel/Dancer-Plugin-DBIC/lib/Dancer/Plugin/DBIC.pm&lt;br /&gt;
* http://search.cpan.org/~flora/DBIx-Class-PassphraseColumn-0.02/lib/DBIx/Class/PassphraseColumn.pm&lt;br /&gt;
&lt;br /&gt;
== Custom Perl ==&lt;br /&gt;
&lt;br /&gt;
Installing a custom version of Perl just for a single user (e.g a project) without breaking the system-wide Perl.&lt;br /&gt;
&lt;br /&gt;
Packages required:&lt;br /&gt;
&lt;br /&gt;
 gcc patch bzip2 gcc-c++ make automake&lt;br /&gt;
&lt;br /&gt;
As the unprivileged user:&lt;br /&gt;
&lt;br /&gt;
 $ curl -L https://install.perlbrew.pl | bash&lt;br /&gt;
 $ source ~/perl5/perlbrew/etc/bashrc&lt;br /&gt;
 $ perlbrew install perl-5.20.1&lt;br /&gt;
 $ perlbrew switch perl-5.20.1&lt;br /&gt;
 $ perlbrew install-cpanm&lt;br /&gt;
 $ echo 'source /home/plates/perl5/perlbrew/etc/bashrc' &amp;gt;&amp;gt; ~/.bashrc&lt;br /&gt;
&lt;br /&gt;
After this you should be always using Perl 5.20.1 as this user (that's what the perlbrew switch does). To install modules, simply use ''cpanm'' followed by the module name.&lt;br /&gt;
&lt;br /&gt;
== Extra Perl modules for Catalyst dev ==&lt;br /&gt;
&lt;br /&gt;
After installing a custom version of Perl as above it's a good idea to install a bunch of frequently used modules if you're doing any kind of Catalyst development.&lt;br /&gt;
&lt;br /&gt;
 cpanm Catalyst::Devel DBIx::Class::TimeStamp DBIx::Class::PassphraseColumn \&lt;br /&gt;
   DBIx::Class::InflateColumn::Serializer Catalyst::Model::DBIC::Schema \&lt;br /&gt;
   Catalyst::Plugin::Authentication Catalyst::Plugin::Authorization::Roles \&lt;br /&gt;
   Catalyst::Plugin::Session Catalyst::Plugin::Session::Store::DBI \&lt;br /&gt;
   Catalyst::Plugin::Session::State::Cookie Catalyst::Plugin::StatusMessage \&lt;br /&gt;
   Catalyst::Authentication::Store::DBIx::Class Catalyst::View::TT \&lt;br /&gt;
   Catalyst::View::JSON Log::Log4perl::Catalyst DBD::mysql Email::Valid \&lt;br /&gt;
   Text::CSV_XS LWP::Protocol::https XML::Simple XML::Writer GD::Image \&lt;br /&gt;
   GD::Text FCGI::ProcManager Catalyst::View::Email::Template \&lt;br /&gt;
   Template::Plugin::DateTime HTML::Tiny Hashids Term::Size::Any Time::ParseDate&lt;br /&gt;
&lt;br /&gt;
== Accessing SQL Server from Perl ==&lt;br /&gt;
&lt;br /&gt;
Install the freetds software (both main package and devel)&lt;br /&gt;
&lt;br /&gt;
 yum install freetds freetds-devel&lt;br /&gt;
&lt;br /&gt;
Configure a server definition in the global config file, I'm not sure there's a way to avoid having to do this.&lt;br /&gt;
&lt;br /&gt;
 cat &amp;gt;&amp;gt; /etc/freetds.conf &amp;lt;&amp;lt;EOF&lt;br /&gt;
 [myserver]&lt;br /&gt;
   host = 192.168.1.4&lt;br /&gt;
   port = 1433&lt;br /&gt;
   tds version = 7.0&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Test the connection using the following:&lt;br /&gt;
&lt;br /&gt;
 tsql -S myserver -U myuser&lt;br /&gt;
&lt;br /&gt;
You should be prompted for a password (SQL auth, not Windows!) and hopefully after providing one, you should see a prompt &amp;lt;code&amp;gt;1)&amp;lt;/code&amp;gt; waiting for an SQL query.&lt;br /&gt;
&lt;br /&gt;
Run the following query to see the available databases.&lt;br /&gt;
&lt;br /&gt;
 SELECT name, database_id, create_date&lt;br /&gt;
 FROM sys.databases;&lt;br /&gt;
 GO&lt;br /&gt;
&lt;br /&gt;
If this didn't work, go back and check your setup.&lt;br /&gt;
&lt;br /&gt;
Install the perl module for DBD::Sybase - don't bother with the ODBC method, this way works just fine.&lt;br /&gt;
&lt;br /&gt;
 SYBASE=/usr cpanm DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
Connect using Perl and DBD::Sybase&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/env perl&lt;br /&gt;
 use DBI;&lt;br /&gt;
 my $dbh = DBI-&amp;gt;connect(&amp;quot;DBI:Sybase:server=myserver&amp;quot;,&amp;quot;myuser&amp;quot;,&amp;quot;mypass&amp;quot;) or die $DBI::errstr;&lt;br /&gt;
 $dbh-&amp;gt;disconnect();&lt;br /&gt;
&lt;br /&gt;
If this works, you're all set.&lt;br /&gt;
&lt;br /&gt;
== DBIx::Class ==&lt;br /&gt;
&lt;br /&gt;
=== Relationships ===&lt;br /&gt;
&lt;br /&gt;
'''belongs_to''' means: a field (or fields) in THIS table is a foreign key (contains the primary key of) THAT other table.&lt;br /&gt;
&lt;br /&gt;
'''has_many''' means: there are multiple (zero or more) rows in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''has_one''' means: there ''is'' a row in THAT table which contains THIS tables primary key.&lt;br /&gt;
&lt;br /&gt;
'''might_have''' means: the same as '''has_one''', except its not guaranteed to be there.&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Mixing STDOUT and STDERR output in the right order ===&lt;br /&gt;
&lt;br /&gt;
STDOUT and STDERR are block buffered when there is no terminal, or line buffered when there is a terminal. This has the unfortunate side effect of making output from print/warn mess up when running a script from cron when the same script works perfectly run from the command line.&lt;br /&gt;
&lt;br /&gt;
Redirect STDERR to the same stream as STDOUT (equiv to 2&amp;gt;&amp;amp;1 in bash) - this isn't essential, but makes it easier to pipe the output through tail/mail/etc, or redirect the output to a logfile.&lt;br /&gt;
&lt;br /&gt;
 close(STDERR);&lt;br /&gt;
 open(STDERR, &amp;quot;&amp;gt;&amp;amp;STDOUT&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Make both streams non-buffering&lt;br /&gt;
&lt;br /&gt;
 select(STDERR);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
 select(STDOUT);&lt;br /&gt;
 $| = 1;&lt;br /&gt;
&lt;br /&gt;
Alternatively, instead of the select() above, you can use IO::Handle&lt;br /&gt;
&lt;br /&gt;
 use IO::Handle;&lt;br /&gt;
 STDERR-&amp;gt;autoflush(1);&lt;br /&gt;
 STDOUT-&amp;gt;autoflush(1);&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=Windows10&amp;diff=362</id>
		<title>Windows10</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=Windows10&amp;diff=362"/>
				<updated>2018-09-06T12:46:03Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* View image EXIF data */ checksum files&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Enabling the Windows 10 lock screen image information ==&lt;br /&gt;
&lt;br /&gt;
Click on Start &amp;gt; Run and type '''control userpasswords2''' to open the user management dialog. Click on the Advanced tab and untick the checkbox at the bottom for ''Require users to press Ctrl-Alt-Delete''&lt;br /&gt;
&lt;br /&gt;
== Comparison of files or folders ==&lt;br /&gt;
&lt;br /&gt;
Install '''WinMerge''' from [http://winmerge.org/ winmerge.org] - it includes a shell extension to allow easy comparison of files or folders.&lt;br /&gt;
&lt;br /&gt;
== View image EXIF data ==&lt;br /&gt;
&lt;br /&gt;
Picture Information Extractor (PIE) - free download&lt;br /&gt;
&lt;br /&gt;
* [https://www.picmeta.com/download.htm picmeta.com]&lt;br /&gt;
&lt;br /&gt;
== Checksum files ==&lt;br /&gt;
&lt;br /&gt;
Works in Windows 7 and 8 too.&lt;br /&gt;
&lt;br /&gt;
 certutil -HashFile filename.zip MD5&lt;br /&gt;
 certutil -HashFile filename.zip SHA1&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	<entry>
		<id>https://wiki.leaky.org/index.php?title=CentOS7&amp;diff=361</id>
		<title>CentOS7</title>
		<link rel="alternate" type="text/html" href="https://wiki.leaky.org/index.php?title=CentOS7&amp;diff=361"/>
				<updated>2018-08-14T18:17:17Z</updated>
		
		<summary type="html">&lt;p&gt;Leaky: /* Enable firewall */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also [[Upstart]]&lt;br /&gt;
&lt;br /&gt;
== Change server hostname ==&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# hostnamectl status&lt;br /&gt;
 &lt;br /&gt;
   Static hostname: localhost.localdomain&lt;br /&gt;
         Icon name: computer-vm&lt;br /&gt;
           Chassis: vm&lt;br /&gt;
        Machine ID: 399b74f54385ee0d782648666a204c25&lt;br /&gt;
           Boot ID: 411893b81fee4fb0b865e1b18fd8dd6d&lt;br /&gt;
    Virtualization: kvm&lt;br /&gt;
  Operating System: CentOS Linux 7 (Core)&lt;br /&gt;
       CPE OS Name: cpe:/o:centos:centos:7&lt;br /&gt;
            Kernel: Linux 3.10.0-123.el7.x86_64&lt;br /&gt;
      Architecture: x86_64&lt;br /&gt;
&lt;br /&gt;
Set the hostname.&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# hostnamectl set-hostname centos7.internal&lt;br /&gt;
&lt;br /&gt;
Check the host name again (Close the session and open new session using putty or console)&lt;br /&gt;
&lt;br /&gt;
== CentOS7 kernel panic on some hardware ==&lt;br /&gt;
&lt;br /&gt;
If you can't even get the installer to work and it just causes a kernel panic on startup, check this link: http://centosfaq.org/centos/centos-72-kernel-panic/&lt;br /&gt;
&lt;br /&gt;
The relevant info is pasted below in case the page is removed in the future.&lt;br /&gt;
&lt;br /&gt;
During the startup of the installer, edit the options for the kernel to include:&lt;br /&gt;
&lt;br /&gt;
 initcall_blacklist=clocksource_done_booting&lt;br /&gt;
&lt;br /&gt;
If the machine is already installed and you're moving the disks to another system and get a kernel panic, it's possible to use an older rescue disk and&lt;br /&gt;
&lt;br /&gt;
Append the line&lt;br /&gt;
&lt;br /&gt;
 GRUB_CMDLINE_LINUX_DEFAULT=”initcall_blacklist=clocksource_done_booting”&lt;br /&gt;
&lt;br /&gt;
to /etc/default/grub, and run&lt;br /&gt;
&lt;br /&gt;
 # grub2-mkconfig &amp;gt; /boot/grub2/grub.cfg&lt;br /&gt;
&lt;br /&gt;
On reboot this should allow you to boot succesfully.&lt;br /&gt;
&lt;br /&gt;
== Enable firewall ==&lt;br /&gt;
&lt;br /&gt;
Start the firewall running and set it to auto-start on bootup&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# systemctl start firewalld&lt;br /&gt;
 [root@localhost ~]# systemctl enable firewalld&lt;br /&gt;
&lt;br /&gt;
Enable HTTP and HTTPS&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=http&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-service=https&lt;br /&gt;
&lt;br /&gt;
Add a custom port for SSH&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --add-port=22222/tcp&lt;br /&gt;
&lt;br /&gt;
Remove the original SSH service&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public --remove-service=ssh&lt;br /&gt;
&lt;br /&gt;
Add a rule for access to a service on a specific local port from a specific source IP&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --permanent --zone=public \&lt;br /&gt;
     --add-rich-rule='rule family=&amp;quot;ipv4&amp;quot; source address=&amp;quot;1.2.3.0/24&amp;quot;&lt;br /&gt;
     port protocol=&amp;quot;tcp&amp;quot; port=&amp;quot;22222&amp;quot; accept'&lt;br /&gt;
&lt;br /&gt;
Block a single IP from all services (and yes, that's a real IP that was pounding on a WordPress login page)&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --add-rich-rule=&amp;quot;rule family='ipv4' source address='176.28.22.192' reject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Reload the firewall rules&lt;br /&gt;
&lt;br /&gt;
 [root@localhost ~]# firewall-cmd --reload&lt;br /&gt;
&lt;br /&gt;
== Disable firewalld and use iptables ==&lt;br /&gt;
&lt;br /&gt;
(content taken from racktables.com in case it disappears)&lt;br /&gt;
&lt;br /&gt;
The first step is to stop and mask the firewalld service (i.e., the service you do not want to use):&lt;br /&gt;
&lt;br /&gt;
 $ systemctl stop firewalld&lt;br /&gt;
 $ systemctl mask firewalld&lt;br /&gt;
&lt;br /&gt;
Then, install the &amp;quot;iptables-services&amp;quot; package (if it is not already installed):&lt;br /&gt;
&lt;br /&gt;
 $ yum install iptables-services&lt;br /&gt;
&lt;br /&gt;
Enable the service to start at boot-time:&lt;br /&gt;
&lt;br /&gt;
 $ systemctl enable iptables&lt;br /&gt;
&lt;br /&gt;
If you are saving your rules in that /etc/sysconfig/iptables file, you will then need to run one of the following commands:&lt;br /&gt;
&lt;br /&gt;
 $ service iptables restart  # OR:&lt;br /&gt;
 $ systemctl restart iptables&lt;br /&gt;
&lt;br /&gt;
Next, check that the iptables service is &amp;quot;active&amp;quot; with:&lt;br /&gt;
&lt;br /&gt;
 $ systemctl status iptables&lt;br /&gt;
&lt;br /&gt;
You can query the systemd journal for a &amp;quot;log&amp;quot; of the changes you made to the iptables service with:&lt;br /&gt;
&lt;br /&gt;
 $ journalctl -f -u iptables.service&lt;br /&gt;
&lt;br /&gt;
== Enable disk quota on ext4 ==&lt;br /&gt;
&lt;br /&gt;
Add to /etc/fstab the following options on the line with the ext4 fs (eg /home):&lt;br /&gt;
&lt;br /&gt;
 usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0&lt;br /&gt;
&lt;br /&gt;
Then check quotas and enable them&lt;br /&gt;
&lt;br /&gt;
 # quotaoff -a&lt;br /&gt;
 # quotacheck -auvgm&lt;br /&gt;
 # quotaon -a&lt;br /&gt;
&lt;br /&gt;
To check the quotas&lt;br /&gt;
&lt;br /&gt;
 # repquota -auv&lt;/div&gt;</summary>
		<author><name>Leaky</name></author>	</entry>

	</feed>