User:Feystorm

Here is some notes I'm keeping and storing here in the hope that google might turn up results on this page and make some people's lives easier.

garbled or distorted vga console with xorg
So I've ran into this problem on several of my machines (coincidentally all nvidia). Basically the problem is when using vga console mode and switching to a terminal after launching xorg. The best way to describe it is the console will be widely spaced out vertically with the normal 80x25 height font in the background, and the vga mode resolution font you selected on top of it.

I eventually gave up on the issue, but here is what I found. The only way to get the console clean again is to run a util like 'resizecons' (from the kbd package), or SVGATextMode (just a theory, didnt try it, but supposedly does the same thing). However this just makes the console readable again. For some reason it doesnt get the number of lines restored properly, and a couple lines will still go off the bottom of the screen (though it is less than when it is in the distorted mode). My box is x86_64, and for some reason the kbd package doesnt install resizecons on this arch. So I had to manually download the package and compile that binary. The magic that seems to somewhat fix this is that it uses the ioctl VT_RESIZE.

But as I mentioned, I eventually gave up on trying to solve this and went over to the dark side (framebuffer).

vesafb vs. uvesafb
So I was tring to determine which of the two was the better choice, and the primary concern was speed. I couldnt find anywhere that documented which method of framebuffer was faster, so I set out to conduct an experiment and see. To cut to the chase, uvesafb is *WAY* faster than vesafb.

In my experiment I ran `time` on catting a 4k file. With vesafb, this took on average 4 seconds (default settings). With uvesafb, the same operation took on average about 0.2 seconds. So in my setup, uvesafb is approximately 20 times faster than vesafb, both with default settings.

Thunar and cifs/smb
Getting thunar to access cifs/smb natively is actually quite easy. Unfortunately there is diddly squat for documentation on how to do it. All you need is to emerge the gnome-base/gvfs package with the samba use flag enabled. After that you'll have to log out and back in for dbus perms to take effect (so dbus needs to be running), but after that just enter 'smb://host/share' in the Thunar path bar and it'll access whatever remote share you want without actually having to mount it manually. For shares that require a authentication, its 'smb://user@host/share'.

On-demand ssh tunnel
This is how to setup ssh tunnels that start up on demand when connected to.


 * Setup ssh public key authentication to the host you wish to tunnel through
 * Install the xinetd package.
 * Create a file in /etc/xinetd.d similar to the following


 * Start xinetd

It is important to set the 'user' attribute to the user who's public key you want to use. It will also use the known_hosts file for this user, so make sure to log into the box at least once an accept the fingerprint.

In the above configuration, any connections to 127.0.0.1:1234 will be tunneled through proxyhost.example.com to target.example.com:2345. The tunnel will shut down as soon as the connection is closed. You can adjust the ssh parameters like compression as desired.

ACPI
Control of the backlight and most of the rest of the ACPI system requires you to enable 2 critical options that are a PITA to find; CONFIG_ACPI_WMI and CONFIG_HP_WMI. The backlight itself requires CONFIG_ACPI_VIDEO. Once all these options are enabled (and loaded), you can control the backlight through /sys/class/backlight/acpi_video0/brightness. Note, I also found that these modules have to be loaded before nvidia if you are using it. I dont know why but if you load them after, /sys/class/backlight never shows up.

Sound
Uses the Sigmatel IDT 92HD75B3X5 chipset.

Requires the following enabled kernel options

CONFIG_SND_HDA_INTEL CONFIG_SND_HDA_CODEC_SIGMATEL

For the headphone jack to work, you then need to add options snd-hda-intel model=hp-dv5 to /etc/modprobe.d/alsa.conf (or any file in that dir).

wine & mono
If you have the unfortunate need to run windows apps requiring mono, theres a simple fix you have to do if you dont want to install mono through portage, but install it just in the wine environment.


 * use winetricks to install mono28 (mono210 hangs during install when I tried)
 * cd to ~/.wine/drive_c/Program Files/Mono-2.8.2/bin
 * symlink mono-2.0.dll to mono.dll

Without the symlink, attempting to run a mono app through wine will just result in wine: Install the Windows version of Mono to run .NET executables

boinc gui
When attempting to use the boinc GUI interface, it was refusing to connect to the local boinc client, even with 'ALLOW_REMOTE_RPC="yes"' in /etc/conf.d/boinc. In simple view, it was presenting the error "unable to connect to the core client". To solve this issue, switch to advanced view, go to advanced->select computer, put in '127.0.0.1' (this was the critical part for me as 'localhost' wouldnt work' but '127.0.0.1' would), and for password put the contents of /var/lib/boinc/gui_rpc_auth.cfg

If you wish to change the authentication password, just shut down boinc, edit /var/lib/boinc/gui_rpc_auth.cfg and start it back up.

FreeRADIUS wireless authentication via LDAP bind
I have a wireless router running DD-WRT and I wanted to be able to authenticate users against an LDAP database via LDAP bind (and not have to give the password, encrypted or unencrypted, to freeradius). I couldnt find any documentation on how to do this anywhere (at least not any documentation that worked). This is how I got it to work.

Server

 * FreeRADIUS version - 2.1.12
 * Router IP - 192.168.0.1
 * Shared secret - secret1234

Configure modules/ldap ldap{} section with your LDAP server configuration. This is fairly straightforward, but is dependent upon your LDAP configuration. I did not set the identity or password attributes as anonymous bind is able to look up users (though the userPassword attribute is restricted). I also set edir_account_policy_check to no.

Configure eap.conf. In the eap { tls {} } section, configure your certificates. For the dh_file, you can create it with `openssl dhparam -out server.dh 1024`. For the random_file parameter, I specified /dev/urandom

Configure clients.conf. Add a section for your router similar to the following client router { ipaddr = 192.168.0.1 secret = secret1234 require_message_authenticator = no  nastype = other }

Configure sites-enabled/inner-tunnel.
 * Go to the authorize section and uncomment "ldap"
 * Go to the authenticate section and change the contents of "Auth-Type PAP" from "pap" to "ldap"

Router

 * Security mode - WPA2 Enterprise
 * Radius Auth Server Address - 192.168.0.2
 * Radius Auth Server Port - 1812
 * Radius Auth Shared Secret - secret1234

Client
I use NetworkManager for wireless management, and configuring it is pretty simple.

Under the Wireless Security tab
 * Security - WPA & WPA2 Enterprise
 * Authentication - Protected EAP (PEAP)
 * Anonymous identity - *blank*
 * CA certificate - (None)
 * PEAP version - Automatic
 * Inner authentication - GTC
 * Username - *LDAP user, just the name not DN*
 * Password - *LDAP pass*

KVM & bridging
While attempting to setup a VM through virt-manager, I was unable to get traffic from the VM to cross the bridge. Doing a tcpdump on the VM's interface (vnet0) showed DHCP requests, but a tcpdump on the bridge interface (virbr0) would not show them. Thus dnsmasq was unable to see the queries, and respond to them. Turns out the issue is that the VM's mac address must start with 52. This makes absolutely no sense, but thats just what I observed. So a valid mac address would be 52:00:00:00:00:00.

EncFS & autofs/fstab
For some stupid reason encfs goes against all standard practices for taking arguments from fuse. This makes it impossible to mount from autofs or fstab (and not have it prompt for a password).

So I wrote a custom wrapper script that makes encfs behave as it should so that it can take arguments when called by fuse, and not by the user.

Create /usr/bin/EncFS with the following contents and chmod it to 755

Then for the fuse filesystem type, use "EncFS" (note the case difference, this needs to match the script filename).

Example: mount -t fuse -o extpass="cat /path/to/password" EncFS#/mount/source /mount/dest

Note: I advised placing the script in /usr/bin as opposed to /usr/local/bin because the script needs to be in $PATH, and when autofs is started its PATH does not contain /usr/local/bin. You can put it in /usr/local/bin if you dont use autofs, or if you want to modify the path used by autofs.

PulseAudio per-application volume control
PulseAudio supports per-application volume control, but by default this doesnt do much as you can only control these volumes from the pulseaudio volume control utility. Meaning that in an application like Audacious, when the output device is set to PulseAudio, and the volume control is set to hardware, it will adjust the master volume control, not the per-application volume control.

To fix this behavior, set the following in /etc/pulse/daemon.conf flat-volumes = no

Now whenever Audacious goes to adjust the volume, it will adjust the audacious only volume and thus you wont have multiple applications fighting over the master volume control.

Log database
I ended up switching all my logging to a database instead of files. I dont mean a client/server database like MySQL or Postgres, but an embedded database; SQLite.

This approach has 2 main benefits
 * No more log rotating. Instead of having to rotate logs at fixed intervals, a simple SQL query can delete the logs you want.
 * Easy/fast searching. Instead of having to look through multiple rotated or priority-filtered logs, having to read a huge log to look for specific time frame, filter out debugging messages, etc, you can search for exactly what you want.

Setup
Required use flags
 * app-admin/syslog-ng sql
 * dev-db/libdbi-drivers sqlite3

httpd
httpd (apache2 as gentoo likes to call it) writes out directly to files by default. This behavior can be changed but requires a little extra work. httpd supports writing the error log straight to syslog, but for some reason not the info log. You could write out to a file and then have syslog-ng read that file in, but I dont like that solution as now you have to start cleaning up files. And writing to a fifo (named pipe) you run the risk of filling the pipe's buffer if syslog-ng dies.

Using
To read the logs I have written a perl script to query the database. For the source code, see below.

Example commands:

Show all log entries from postfix as they come in

Show all emergency and alert messages that have occurred since 24 hours ago.

Delete all debugging messages older than 1 week ago

{{FileBox|filename=/usr/local/bin/logs|lang=perl|1=
 * 1) !/usr/bin/perl
 * 2) Copyright (C) 2012 Patrick A. Hemmer
 * 3) 
 * 4) This program is free software; you can redistribute it and/or
 * 5) modify it under the terms of the GNU General Public License
 * 6) as published by the Free Software Foundation; either version 2
 * 7) of the License, or (at your option) any later version.
 * 8) This program is distributed in the hope that it will be useful,
 * 9) but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 10) MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * 11) GNU General Public License for more details.
 * 12) You should have received a copy of the GNU General Public License
 * 13) along with this program; if not, write to the Free Software
 * 14) Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 1) You should have received a copy of the GNU General Public License
 * 2) along with this program; if not, write to the Free Software
 * 3) Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 1) Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

use warnings; use strict; use DBI; use Sys::Syslog qw(:macros); use Linux::Inotify2; use Getopt::Long; use Date::Manip; use POSIX qw(strftime);

my $dbpath = '/var/log/logs.sql3';

sub xlate { return(Sys::Syslog::xlate(@_)); } # Sys::Syslog doesnt export this, but I want to use it anyway Getopt::Long::Configure('bundling', 'no_auto_abbrev', 'pass_through'); # pass_through is so we can handle the error use constant { 'EQUALITY_NUMERIC' => 1, 'EQUALITY_STRING' => 2, }; $0 =~ m#([^/]+)$#; my $basename = $1; my @priorities = ('emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug'); my @facilities = ('kern', 'user', 'mail', 'daemon', 'auth', 'syslog', 'lpr', 'news', 'uucp', 'cron', 'authpriv', 'ftp', 'ntp', 'audit', 'alert', 'cron', 'local0', 'local1', 'local2', 'local3', 'local4', 'local5', 'local6', 'local7');

my %opts = (	'follow' => 0,	'head' => 0,	'lines' => undef,	#'format' => exists($ENV{'LOGS_FORMAT'}) ? $ENV{'LOGS_FORMAT'} : '%t %p: %m',	'format' => exists($ENV{'LOGS_FORMAT'}) ? $ENV{'LOGS_FORMAT'} : '%{%Y-%m-%d %H:%M:%S} %r: %m',	# %t = Time	# %f = Facility	# %F = Facility (numeric)	# %p = Priority	# %P = Priority (numeric)	# %h = host	# %r = pRogram[pid]	# %R = pRogram	# %i = pId	# %T = Tag	# %m = Message

'delete' => 0, 'vacuum' => 0,

'time' => undef, 'host' => undef, 'facility' => undef, 'priority' => undef, 'program' => undef, 'pid' => undef, 'tag' => undef,

'debug' => 0, 'help' => 0, ); GetOptions( 'lines|n=i' => \$opts{'lines'}, 'follow|f' => \$opts{'follow'}, 'head|H' => \$opts{'head'}, 'format=s' => \$opts{'format'},

'delete' => \$opts{'delete'}, 'vacuum' => \$opts{'vacuum'}, 'time|date|t=s' => \$opts{'time'}, 'host|h=s' => \$opts{'time'}, 'facility|facil|F=s' => \$opts{'facility'}, 'priority|prio|P=s' => \$opts{'priority'}, 'program|prog|p=s' => \$opts{'program'}, 'pid|i=i' => \$opts{'pid'}, 'tag|T=s' => \$opts{'tag'},

'debug' => \$opts{'debug'}, 'help' => \$opts{'help'}, );

if(scalar(@ARGV)) { print(STDERR "Unknown option $ARGV[0]\n"); $opts{'help'} = 2; } if($opts{'help'}) { print <<EOI; Usage: $basename [OPTIONS] -n, --lines=N             Show N messages (default 10) -f, --follow              Show messages as they are added -H, --head                Show the first N lines instead of the last --format              Format to output messages in

--delete                  Delete all matching entries instead of displaying --vacuum                  Vacuum the database after deletion (reclaims                             free space).

-t, --time=TIME         # Show only lines matching time TIME --date=TIME         # Same as --time -h, --host=HOST         * Show only lines matching host HOST -F, --facility=FACILITY * Show only lines matching facility FACILITY --facil=FACILITY    # Same as --facility -P, --priority=PRIORITY # Show only lines matching priority PRIORITY --prio=PRIORITY     # Same as --priority -p, --program=PROGRAM   * Show only lines matching program PROGRAM --prog=PROGRAM      * Same as --program -i, --pid=PID           # Show only lines matching pid PID -T, --tag=TAG           * Show only lines matching tag TAG

--help                This

Filters: Above filters denoted with '*' support matching based on numeric operators. eg. `$basename --priority '<=notice'` Above filters denoted with '#' support matching based on globbing. eg. `$basename --program 'postfix/*'`

Priorities:        Facilities: 0 = emerg          0  = kern      8  = uucp      16 = local0 1 = alert          1  = user      9  = cron      17 = local1 2 = crit           2  = mail      10 = authpriv  18 = local2 3 = err            3  = daemon    11 = ftp       19 = local3 4 = warning        4  = auth      12 = (ntp)     20 = local4 5 = notice         5  = syslog    13 = (audit)   31 = local5 6 = info           6  = lpr       14 = (alert)   32 = local6 7 = debug          7  = news      15 = (cron)    33 = local7 Facilities in are not official

Format options: %{} = strftime (strftime parameters are enclosed in the braces) %t = Time                 %r = pRogram[pid] %f = Facility             %R = pRogram %F = Facility (numeric)   %i = pId %p = Priority             %T = Tag %P = Priority (numeric)   %m = Message %h = Host EOI if($opts{'help'} > 1) { exit(1); }	exit(0); } if($opts{'delete'} && $opts{'follow'}) { print(STDERR "Cant use --follow with --delete\n"); exit(1); } if($opts{'head'} && $opts{'follow'}) { print(STDERR "Cant use --follow with --head\n"); exit(1); } if($opts{'delete'} && defined($opts{'lines'})) { print(STDERR "Can't use --lines with --delete\n"); exit(1); }

if($opts{'delete'}) { $opts{'head'} = 1; } if(!$opts{'delete'} && !defined($opts{'lines'})) { $opts{'lines'} = 10; }

my $db = DBI->connect("dbi:SQLite:dbname=$dbpath",,) || die($DBI::errstr); $db->do('pragma cache_size = 24576'); # set a 24mb cache

my $sth = gen_sth(%opts); if($opts{'debug'}) { print($sth->{'Statement'} . "\n"); exit(0); } if($opts{'delete'}) { $sth->execute; if($opts{'vacuum'}) { $sth = $db->prepare('select min(id) from logs'); $sth->execute; if(my $row = $sth->fetchrow_arrayref) { $db->do('update logs set id = id - ' . $row->[0]); # start the log entries back at 0 }

$db->do('vacuum'); }	$db->commit; } elsif(!$opts{'follow'}) { batch($sth, -1); } else { my $in = Linux::Inotify2->new; $in->watch($dbpath, IN_MODIFY); my $last_id = batch($sth, -1); $opts{'time'} = undef; $opts{'lines'} = undef; my $sth = gen_sth(%opts); do { $last_id = batch($sth, $last_id); } while(defined($in->read)); } exit(0);

sub batch { my $sth = shift; my $last_id = shift;

for my $message (fetch($sth, $last_id)) { my $line = $opts{'format'}; $line =~ s/\%\{([^}]+)\}/strftime($1, localtime($message->[1]))/eg; $line =~ s/\%(.)/fmt($1, $message)/eg; print($line . "\n"); $last_id = $message->[0]; }	return($last_id); } sub fmt { my $code = shift; my $message = shift;

# %t = time # %f = Facility # %F = Facility (numeric) # %p = Priority # %P = Priority (numeric) # %h = host # %r = pRogram[pid] # %R = pRogram # %i = pId # %T = Tag # %m = Message

# message # [0] = id	# [1] = time # [2] = time_r # [3] = host # [4] = facility # [5] = priority # [6] = program # [7] = pid # [8] = tag # [9] = message

if($code eq 't') { return(strftime('%Ec', localtime($message->[1]))) }	if($code eq 'f') { return($facilities[$message->[4]]); }	if($code eq 'F') { return($message->[4]); }	if($code eq 'p') { return($priorities[$message->[5]]); }	if($code eq 'P') { return($message->[5]); }	if($code eq 'h') { return($message->[3]); }	if($code eq 'r') { return($message->[6] . (defined($message->[7]) ? '[' . $message->[7]. ']' : ''));	}	if($code eq 'R') { return($message->[6]); }	if($code eq 'i') { return($message->[7]); }	if($code eq 'T') { return($message->[8]); }	if($code eq 'm') { return($message->[9]); }	if($code eq '%') { return('%'); }	return('%' . $code); # unknown, spit it back out }

sub gen_sth { my $opts = %_; my $q = ''; if($opts{'delete'}) { $q .= 'delete '; } else { $q .= 'select id,time,time_r,host,facility,priority,program,pid,tag,message '; }	$q .= 'from logs ';

my @wheres = ;

if(defined($opts{'time'})) { my ($equality, $value) = equality(EQUALITY_NUMERIC, $opts{'time'}); if($value =~ /^\d+$/) { # unix timestamp push(@wheres, 'time ' . $equality . ' ' . $value); } else { # parse the date into a timestamp my $unixdate = UnixDate(ParseDate($value), '%s'); if(!defined($unixdate)) { print(STDERR "Could not parse time '$value'\n"); exit(1); }			push(@wheres, 'time ' . $equality . ' ' . $unixdate); }	}	if(defined($opts{'program'})) { my ($equality, $value) = equality(EQUALITY_STRING, $opts{'program'}); push(@wheres, 'program ' . $equality . ' ' . $value); }	if(defined($opts{'host'})) { my ($equality, $value) = equality(EQUALITY_STRING, $opts{'host'}); push(@wheres, 'host ' . $equality . ' ' . $value); }	if(defined($opts{'tag'})) { my ($equality, $value) = equality(EQUALITY_STRING, $opts{'tag'}); push(@wheres, 'tag ' . $equality . ' ' . $value); }	if(defined($opts{'pid'})) { my ($equality, $value) = equality(EQUALITY_NUMERIC, $opts{'pid'}); push(@wheres, 'pid ' . $equality . ' ' . $value); }	if(defined($opts{'facility'})) { my ($equality, $value) = equality(EQUALITY_NUMERIC, $opts{'facility'}); my $facility = xlate($value); if($facility == -1) { print(STDERR "Could not parse facility '$value'\n"); exit(1); }		push(@wheres, 'facility ' . $equality . ' ' . $facility); }	if(defined($opts{'priority'})) { my ($equality, $value) = equality(EQUALITY_NUMERIC, $opts{'priority'}); my $priority = xlate($value); if($priority == -1) { print(STDERR "Could not parse priority '$value'\n"); exit(1); }		push(@wheres, 'priority ' . $equality . ' ' . $priority); }

if(!$opts{'delete'}) { push(@wheres, 'id > ?'); }

$q .= 'where '. join(' and ', @wheres). ' ';

if(!$opts{'delete'}) { if($opts{'head'}) { $q .= 'order by time asc '; } else { $q .= 'order by time desc '; }		if($opts{'lines'}) { $q .= 'limit '. $opts{'lines'}. ' ';		}	}	my $sth = $db->prepare($q) || die($q . "\n" . $db->errstr); if($opts{'head'}) { $sth->{'private_reverse'} = 0; } else { $sth->{'private_reverse'} = 1; }	return($sth); }

sub fetch { my $sth = shift; my $id_after = shift;

my $r = $sth->execute($id_after) || die($db->errstr); my @rows; if(!$sth->{'private_reverse'}) { @rows = @{$sth->fetchall_arrayref}; } else { # we ordered with oldest first, reverse to get normal order @rows = reverse(@{$sth->fetchall_arrayref}); }	return(@rows); }

sub equality { my $type = shift; my $data = shift;

if($type == EQUALITY_NUMERIC) { if($data =~ /^\s*([<>=]=?)\s*(.+)?\s*$/) { return($1, $2); } else { #print(STDERR "Unable to parse numeric atom: '$data'\n"); #exit(2); return('=', $data); }	} elsif($type == EQUALITY_STRING) { if($data =~ /^\s*=/) { return('=', $'); }		$data =~ s/\\/\\\\/g; $data =~ s/%/\\%/g; $data =~ s/_/\\_/g; $data =~ s/\*/%/g; $data =~ s/\?/_/g; $data =~ s/'/''/g; return('like', "'" . $data . "'"); } else { die("Shouldnt be here\n"); } } }}

Sane GRUB2 config
I see a lot of people not wanting to upgrade to GRUB2 because of its stupidly complex configuration. Unfortunately none of the howto guides explain that its possible to dramatically simplify the config into something similar to what grub1 was like. You dont have to regenerate all the grub configs every time you build a new kernel, all you do is edit one file just like you did with grub1.

Here's what my grub2 config file looks like:

Clean, simple, and easy to read.

Here's how.

Custom entry
Create a custom entry in the standard configuration. This is just to be 'proper'.

This tells grub to look for the file /boot/grub2/custom.cfg and if it exists, include its contents

Regenerate config
This will be the last time you have to do this.

custom.cfg
Create /boot/grub2/custom.cfg with the contents similar to the file I show up above.

To make things even simpler I symlink /boot/grub2/custom.cfg to /boot/boot.cfg. There are very few files in /boot and so its easier to spot.

Use it
Thats it. Grub2 will automatically read in the custom.cfg on boot. Whenever you make a change to it, you dont need to run grub2-mkconfig any more.