RSS | technovelty home | page of ian | ian@wienand.org
I'd wager probably more people today don't know what the TERM environment variable really does than do (yes, everyone who used to use ed over a 300-baud acoustic-coupler is laughing, but times have changed!).
I recently got hit by what was, at the time, a strange bug. Consider the following trivial Python program, that uses curses and issues the "hide the cursor" command.
$ cat curses.py import curses curses.initscr() curses.curs_set(0) curses.nocbreak() curses.echo() curses.endwin()
If you run it in your xterm or linux console, nothing should happen. But change your TERM to vt102 and it won't work:
$ TERM=vt102 python ./test.py
Traceback (most recent call last):test-curses.py
File "./test-curses.py", line 5, in <module>
curses.curs_set(0)
_curses.error: curs_set() returned ERR
(obvious when you explicitly reset the term, no so obvious when some script is doing it behind your back -- as I can attest!) So, what really happened there? The curs_set man page gives us the first clue:
curs_set returns the previous cursor state, or ERR if the requested visibility is not supported.
How do we know if visibility is supported? For that, curses consults the terminfo library. This is a giant database streching back to the dawn of time that says what certain terminals are capable of, and how to get them to do whatever it is you want them to do. So the TERM environment variable tells the terminfo libraries what database to use (see /usr/share/terminfo/*) when reporting features to people who ask, such as ncurses. man 5 terminfo tells us:
cursor_invisible | civis | vi | make cursor invisible
So curses is asking terminfo how to make the cursor invisible, and getting back "that's not possible here", and hence throwing our error.
But how can a person tell if their current terminal supports this feature? infocmp will echo out the features and what escape codes are used to access them. So we can check easily:
$ echo $TERM xterm $ infocmp | grep civis bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l, $ TERM=vt102 infocmp | grep civis $
So we can now clearly see that the vt102 terminal doesn't support civis, and hence has no way to make the cursor invisible; hence the error code.
If you're ever looking for a good read, check out the termcap/terminfo master file. The comments are like a little slice of the history of computing!
posted at: Tue, 11 May 2010 15:58 | in /linux | permalink | add comment (10 others)
Mark this one down as another in the long list of "duh" — once you realise what is going on!
Bug report comes in about a long running daemon that has stopped logging. lsof reports the log file is now named logfile~ and further more is deleted! This happens after a system upgrade scenario, so of course I go off digging through a multitude of scripts and what-not to find the culprit...
Have you got it yet?
Try this...
# lsof | grep syslogd | grep messages syslogd 1376 root 15w REG 3,1 99851 4605625 /var/log/messages
# cd /var/log/ # vi messages (and save the file)
root@jj:/var/log# lsof | grep syslogd | grep messages syslogd 1376 root 15w REG 3,1 99851 4605625 /var/log/messages~ (deleted)
vi is very careful and renames your existing file, so that if anything goes wrong when writing the new version you can get something back. It's a shame the daemon doesn't know about this! The kernel is happy to deal with the rename, but when the backup file is unlinked you're out of luck. Confusingly to a casual inspection your log file looks like it's there ... just that nothing is going into it. (oh, and if you tried that, you might like to restart syslogd now :)
Moral of the story -- overcome that finger-memory and never use vi on a live file; you're asking for trouble!
posted at: Fri, 08 Jan 2010 16:15 | in /linux/tips | permalink | add comment (6 others)
So, how to strip a shared library?
--strip-unneeded states that it removes all symbols that are not needed for relocation processing. This is a little cryptic, because one might reasonably assume that a shared library can be "relocated", in that it can be loaded anywhere. However, what this really refers to is object files that are usually built and bundled into a .a archive for static linking. For an object in an static library archive to still be useful, global symbols must be kept, although static symbols can be removed. Take the following small example:
$ cat libtest.c
static int static_var = 100;
int global_var = 100;
static int static_function(void) {
return static_var;
}
int global_function(int i) {
return static_function() + global_var + i;
}
Before stripping:
$ gcc -c -fPIC -o libtest.o libtest.c
$ readelf --symbols ./libtest.o
Symbol table '.symtab' contains 18 entries:
Num: Value Size Type Bind Vis Ndx Name
...
5: 00000000 4 OBJECT LOCAL DEFAULT 5 static_var
6: 00000000 22 FUNC LOCAL DEFAULT 3 static_function
13: 00000004 4 OBJECT GLOBAL DEFAULT 5 global_var
16: 00000016 36 FUNC GLOBAL DEFAULT 3 global_function
After stripping:
$ strip --strip-unneeded libtest.o
$ readelf --symbols ./libtest.o
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
...
10: 00000004 4 OBJECT GLOBAL DEFAULT 5 global_var
13: 00000016 36 FUNC GLOBAL DEFAULT 3 global_function
If you --strip-all from this object file, it will remove the entire .symtab section and will be useless for further linking, because you'll never be able to find global_function to call it!.
Shared libraries are different, however. Shared libraries keep global symbols in a separate ELF section called .dynsym. --strip-all will not touch the dynamic symbol entires, and thus it is therefore safe to remove all the "standard" symbols from the output file, without affecting the usability of the shared library. For example, readelf will still show the .dynsym symbols even after stripping:
$ gcc -shared -fPIC -o libtest.so libtest.c
$ strip --strip-all ./libtest.so
$ readelf --syms ./libtest.so
Symbol table '.dynsym' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
...
6: 00000452 36 FUNC GLOBAL DEFAULT 12 global_function
10: 000015e0 4 OBJECT GLOBAL DEFAULT 21 global_var
However, --strip-unneeded is smart enough to realise that a shared-object library doesn't need the .symtab section as well and remove it.
So, conclusions? --strip-all is safe on shared libraries, because global symbols remain in a separate section, but not on objects for inclusion in static libraries (relocatable objects). --strip-unneeded is safe for both, and automatically understands shared objects do not need any .symtab entries to function and removes them; effectively doing the same work as --strip-all. So, --strip-unneeded is essentially the only tool you need for standard stripping needs!
See also
posted at: Wed, 23 Dec 2009 16:39 | in /linux | permalink | add comment (2 others)
Although Django is well packaged for Debian, I've recently come to the conculsion that the packages are really not what I want. The problem is that my server runs Debian stable, while my development laptop runs unstable, and Django revisions definitely fall into the "unstable" category. There really is no way to use a system Django 1.1 on one side, and a system Django 1.0 on the other.
After a bit of work, I think I've got something together that works, and I post it here in the hope it is useful for someone else. This info has been gleaned from similar references such as this and this.
This is aimed at running a server using Debian stable (5.0) for production and an unstable environment for development. You actually need both to get this running. This is based on a project called "project" that lives in /var/www
$ virtualenv --no-site-packages project New python executable in project/bin/python Installing setuptools............done.
/var/www$ cd project /var/www/project$ . bin/activate (project) /var/www/project$
(project) /var/www/project$ easy_install pip Searching for pip Reading http://pypi.python.org/simple/pip/ Reading http://pip.openplans.org Best match: pip 0.4 Downloading http://pypi.python.org/packages/source/p/pip/pip-0.4.tar.gz#md5=b45714d04f8fd38fe8e3d4c7600b91a2 Processing pip-0.4.tar.gz Running pip-0.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Wu9O-U/pip-0.4/egg-dist-tmp-xjSdxq warning: no previously-included files matching '*.txt' found under directory 'docs/_build' no previously-included directories found matching 'docs/_build/_sources' zip_safe flag not set; analyzing archive contents... pip: module references __file__ Adding pip 0.4 to easy-install.pth file Installing pip script to /var/www/project/bin Installed /var/www/project/lib/python2.5/site-packages/pip-0.4-py2.5.egg Processing dependencies for pip Finished processing dependencies for pip
(project) /var/www/project$ easy_install setuptools==0.6c9 Searching for setuptools==0.6c9 Reading http://pypi.python.org/simple/setuptools/ Best match: setuptools 0.6c9 Downloading http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c9-py2.5.egg#md5=fe67c3e5a17b12c0e7c541b7ea43a8e6 Processing setuptools-0.6c9-py2.5.egg Moving setuptools-0.6c9-py2.5.egg to /var/www/project/lib/python2.5/site-packages Removing setuptools 0.6c8 from easy-install.pth file Adding setuptools 0.6c9 to easy-install.pth file Installing easy_install script to /var/www/project/bin Installing easy_install-2.5 script to /var/www/project/bin Installed /var/www/project/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg Processing dependencies for setuptools==0.6c9 Finished processing dependencies for setuptools==0.6c9
(project) /var/www/project$ cat requirements.txt -e svn+http://code.djangoproject.com/svn/django/tags/releases/1.0.3/#egg=Django (project) /var/www/project$ pip install -r requirements.txt Obtaining Django from svn+http://code.djangoproject.com/svn/django/tags/releases/1.0.3/#egg=Django (from -r requirements.txt (line 1)) Checking out http://code.djangoproject.com/svn/django/tags/releases/1.0.3/ to ./src/django (project) /var/www/project$ pip install -r requirements.txt Obtaining Django from svn+http://code.djangoproject.com/svn/django/tags/releases/1.0.3/#egg=Django (from -r requirements.txt (line 1)) Checking out http://code.djangoproject.com/svn/django/tags/releases/1.0.3/ to ./src/django ... so on ...
activate_this = "/var/www/project/bin/activate_this.py" execfile(activate_this, dict(__file__=activate_this)) from django.core.handlers.modpython import handler
(project) /var/www/project$ mkdir project (project) /var/www/project/project$ mkdir db django media www (project) /var/www/project/project$ cd django/ (project) /var/www/project/project/django$ django-admin startproject myproject
DocumentRoot /var/www/project
<Location "/">
SetHandler python-program
PythonHandler project-python
PythonPath "['/var/www/project/','/var/www/project/project/django/'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE myproject.settings
PythonDebug On
</Location>
Alias /media /var/www/project/project/media
<Location "/media">
SetHandler none
</Location>
<Directory "/var/www/project/project/media">
AllowOverride none
Order allow,deny
Allow from all
Options FollowSymLinks Indexes
</Directory>
With all this, you should be up and running in a basic but stable environment. It's easy enough to update packages for security fixes, etc via pip after activating your virtualenv.
posted at: Fri, 11 Sep 2009 22:49 | in /linux/debian | permalink | add comment (6 others)
Here's an interesting behaviour that, as far as I can tell, is completley undocumented, sightly consfusing but fairly logical. Your program should receive a SIGTTOU when it is running in the background and attempts to output to the terminal -- the idea being that you shouldn't scramble the output by mixing it in while the shell is trying to operate. Here's what the bash manual has to say
Background processes are those whose process group ID differs from the terminal's; such processes are immune to key- board-generated signals. Only foreground processes are allowed to read from or write to the terminal. Background processes which attempt to read from (write to) the terminal are sent a SIGTTIN (SIGTTOU) signal by the terminal driver, which, unless caught, suspends the process.
So, consider the following short program, which writes some output and catches any SIGTTOU's, with an optional flag to switch between canonical and non-canonical mode.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <unistd.h>
static void sig_ttou(int signo) {
printf("caught SIGTTOU\n");
signal(SIGTTOU, SIG_DFL);
kill(getpid(), SIGTTOU);
}
int main(int argc, char *argv[]) {
signal(SIGTTOU, sig_ttou);
if (argc != 1) {
struct termios tty;
printf("setting non-canoncial mode\n");
tcgetattr(fileno(stdout), &tty);
tty.c_lflag &= ~(ICANON);
tcsetattr(fileno(stdout), TCSANOW, &tty);
}
int i = 0;
while (1) {
printf(" *** %d ***\n", i++);
sleep(1);
}
}
This program ends up operating in an interesting manner.
$ ./sigttou & *** 0 *** [1] 26171 $ *** 1 *** *** 2 *** *** 3 ***
$ ./sigttou 1 & [1] 26494 ianw@jj:/tmp$ setting non-canoncial mode caught SIGTTOU [1]+ Stopped ./sigttou 1
$ stty tostop $ ./sigttou & [2] 26531 ianw@jj:/tmp$ *** 0 *** caught SIGTTOU [2]+ Stopped ./sigttou
You can see a practical example of this by comparing the difference
between cat file & and more file &.
The semantics make some sense -- anything switching off canonical mode
is like to be going to really scramble your terminal, so it's good to
stop it and let it's terminal handling functions run. I'm not sure
why canoncial background is considered useful mixed in with your
prompt, but someone, somewhere must have decided it was so.
Update: upon further investigation, it is the switching of terminal modes that invokes the SIGTTOU. To follow the logic through more, see the various users of tty_check_change in the tty driver.
posted at: Fri, 21 Aug 2009 11:02 | in /linux/tips | permalink | add comment (0 others)
If you go for an ultrasound or some other imaging procedure, they may give you a CD with the images that requires some overly complicated and under-featured Windows viewer. Chances are these images are in DICOM format, which is like the AVI of the medical world.
Your first clue will be that file might report the file as an unoptimised QuickTime movie, e.g.
$ file ./QMAG0001 ./QMAG0001: Apple QuickTime movie (unoptimized)
After figuring out the file type wasn't actually anything to do with QuickTime, I tried some of the many different tools and methods to convert this to something viewable. Unfortunatley, the DICOM viewer in GIMP and ImageMagick (probably the same thing?) didn't like the files at all, and neither did a range of other tools. I finally managed to do it with the dcm2pnm tool from the Debian dcmtk package -- just point it at the file and it spits out a PNM which is easily converted by all graphics tools.
You can also encapsulate a series of images in a DICOM file, like a little movie. dcm2pnm extracts these easily, but requires the --all-frames options. An ffmpeg recipe to turn these extracted files into a more easily viewable movie is:
$ ffmpeg -qscale 5 -r 20 -b 9600 -i foo.%d.ppm movie.mp4
I certainly can't guarantee this will actually work for you, as DICOM appears to be an extremely complicated format with many possible vendor extensions. But hopefully it's a starting point!
posted at: Sun, 08 Feb 2009 14:11 | in /linux/tips | permalink | add comment (2 others)
I've been meaning to try NoMachine NX for a while. Its promise of fast remote X11 sessions sounded exactly like what I wanted to log into my work desktop remotely (I really like having a remote desktop with saved state you can just pick up from when using remote access). That was pretty much all I knew about the software, so I was a completely blank slate.
The getting started guide is the perfect example of how not to write a getting started guide.
Firstly, Section 1 - "Getting started" - gives me a full history of the product, goes into significant depth about the challenges of forwarding X11 requests, talks about the caching and compression implementation, round-trip latency measurement, the details of two-way proxying system and discusses every other feature of the software.
My eyes glazed over after about the first paragraph. That's all great -- I just want to know what to do!
At this point, I assume that I'm required to run some sort of daemon at the remote end. I download and install the server package (it is explained that the server package requires the client and agent packages as well, fine).
I'm paging down, looking for something to get me started. I'm happy to see Section 7 - "Set up your NX Server environment" (remember, at this point I though I needed some daemon running in the background constantly). It even has some commands commands to type, so I tap away, running nxserver --useradd nxtest --system. My server binary doesn't even seem to recognise these options. I give up, assuming that the server isn't running and nothing will work. The getting started guide has abruptly ended and I have no idea what to do.
As it turns out, it's all completely trivial. Here's the missing "getting started guide".
Additional tips:
Other than the documentation, it really works as promised, making remote X11 usable. One really nice feature is that it is smart about the resolution of the remote desktop, filling up your local screen. Add to that you don't need anything setup but your normal ssh connection, and it's a great remote desktop solution.
posted at: Wed, 04 Feb 2009 15:10 | in /linux/tips | permalink | add comment (8 others)
I've written about AUXV previously, focusing on one of its most interesting applications -- its role in helping find linux-gate.so.1.
If you're starting your program, you can get the dynamic loader to echo out the AUXV fields with the environment variable LD_SHOW_AUXV, but if your process has started you'll need to pull the values out of /proc/pid/auxv directly.
This is pretty internal stuff for the dynamic loader and is probably only useful if you're writing a debugger or doing some other low-level tricks (such as debugging!). However, should you need to, here is some sample code which does just that. Hopefully it will save someone else some time!
posted at: Fri, 03 Oct 2008 16:08 | in /linux | permalink | add comment (0 others)
Here are some slides and examples I used for a kernel course I developed (some time ago now).
The course was aimed at C developers who wanted an introduction to both general UNIX-style user-space and Linux kernel development with a focus on embedded systems issues. The course is aimed at two 8-hour days, and is pretty packed in even then.
The first day is user-space development and kernel building, focusing on things like make, autotools, advanced gcc, getting cross-compilers working, configuring the kernel and building. The second day we get into kernel internals; building up a kernel module to produce some simple proc nodes, take data, crash and debug, etc, look at internals like concurrency and the driver model, and focus on USB quite a bit.
Here is a tarball of the entire thing, including the examples.
Hopefully these can help out anyone tackling the design of such a course.
posted at: Mon, 29 Sep 2008 21:27 | in /linux | permalink | add comment (3 others)
A recent post reminded me of a problem I once had; determine the glibc version and its support for various things.
There's actually a little known but useful confstr call defined for just this sort of thing. Here's a minimal example:
#include <stdio.h>
#include <unistd.h>
#include <alloca.h>
#include <string.h>
int main (void)
{
size_t n = confstr (_CS_GNU_LIBC_VERSION, NULL, 0);
if (n > 0)
{
char *buf = alloca (n);
confstr (_CS_GNU_LIBC_VERSION, buf, n);
printf("%s\n", buf);
}
return 0;
}
man confstr has all the details. If you don't need it in your program, you can also just run /lib/libc/so.6 and it will print out it's version info, e.g.
$ /lib/libc.so.6 GNU C Library stable release version 2.7, by Roland McGrath et al. Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 4.3.1 20080523 (prerelease). Compiled on a Linux >>2.6.24.4<< system on 2008-06-02. Available extensions: crypt add-on version 2.1 by Michael Glad and others GNU Libidn by Simon Josefsson Native POSIX Threads Library by Ulrich Drepper et al BIND-8.2.3-T5B For bug reporting instructions, please see: <http://www.gnu.org/software/libc/bugs.html>.
There's also another glibc trick that often comes in useful; the LD_DEBUG environment variable. Start with help and you can get more details from there.
$ LD_DEBUG=help ls Valid options for the LD_DEBUG environment variable are: libs display library search paths reloc display relocation processing files display progress for input file symbols display symbol table processing bindings display information about symbol binding versions display version dependencies all all previous options combined statistics display relocation statistics unused determined unused DSOs help display this help message and exit To direct the debugging output into a file instead of standard output a filename can be specified using the LD_DEBUG_OUTPUT environment variable.
posted at: Fri, 08 Aug 2008 13:51 | in /linux/tips | permalink | add comment (0 others)
I recently picked up the Netgear WG311 V3 very cheap from Office Depot.
The card seems to work fine with ndiswrapper; there are other guides on getting it working.
The first problem was the reception was, in a word, rubbish. After putting the box back in it's usual home the house wireless was lucky to get a 7/100 signal rating. I found a work-around while the cheap external antenna I ordered is arriving; shield the antenna with foil. This increased signal to between 30-40/100, a considerable boost making it actually useful.
The second problem was coming to terms with wpa_supplicant, of which the details often become very confusing very quickly. Here's the Debian 2-second guide for a simple, standard WPA network I was looking for:
iface wlan0 inet dhcp
# Useful with ifup -v
# wpa-debug-level 3
wpa-conf /etc/wpa_supplicant.conf
network={
ssid="your_ssid"
psk="your_password"
key_mgmt=WPA-PSK
proto=WPA
}
posted at: Sun, 06 Jul 2008 20:48 | in /linux/tips | permalink | add comment (0 others)
Although it's not particularly clear, a neat feature of xtightvnc is the ability to modify the pop-up menu that appears when you press F8 to send arbitrary keystrokes.
The trick is overriding some of the X11 resources of the file. If you have a look in /etc/X11/app-defaults/Vncviewer (make sure you have a recent package) you can see the default keybindings for the popup menu, which are a good template. Assuming you want to keep them all, you can add your own buttons by starting at button 9 and re-defining the total button count in your ~/.Xresources:
xtightvncviewer*popupButtonCount: 11
xtightvncviewer*popup*button9.label: Alt-F1
xtightvncviewer*popup*button9.translations: #override\n\
<Btn1Down>,<Btn1Up>: \
SendRFBEvent(keydown,Alt_L) \
SendRFBEvent(keydown,F1) \
SendRFBEvent(keyup, F1) \
SendRFBEvent(keyup, Alt_L)
xtightvncviewer*popup*button10.label: Alt-F2
xtightvncviewer*popup*button10.translations: #override\n\
<Btn1Down>,<Btn1Up>: \
SendRFBEvent(keydown,Alt_L) \
SendRFBEvent(keydown,F2) \
SendRFBEvent(keyup, F2) \
SendRFBEvent(keyup, Alt_L)
xtightvncviewer*popup*button11.label: Alt-F12
xtightvncviewer*popup*button11.translations: #override\n\
<Btn1Down>,<Btn1Up>: \
SendRFBEvent(keydown,Alt_L) \
SendRFBEvent(keydown,F12) \
Make sure you merge this with xrdb -merge ~/.Xresources if you don't want to bother logging out and in. This way I can easily send Alt-F1, etc. through to the other side; useful for things like switching virtual terminals in VMware workstation running remotely. I imagine if you were insane you could do all sorts of other tricks too!
posted at: Thu, 22 May 2008 16:29 | in /linux/tips | permalink | add comment (0 others)
I found a few people asking how to automate scripts using ssh with the -f option but not many solutions. Th -f option makes the ssh process fork into the background once started, but since it doesn't give you it's PID it becomes hard to kill it once the script ends.
The solution is to setup a control channel with -M. This allows you to communicate to the ssh process and close it down when your process finishes. For example, here is how I open a VNC connection to my desktop at work, which involves going through a corporate ssh firewall box.
ssh -M -S /tmp/vncssh-firewall.ctl -L 2022:desktop.internal.company.com:22 -f -N username@firewall.company.com ssh -M -S /tmp/vncssh-localhost.ctl -N -p 2022 -L 5901:localhost:5901 -f -N username@localhost xtightvncviewer -encodings tight localhost:1 ssh -S /tmp/vncssh-firewall.ctl -O exit localhost ssh -S /tmp/vncssh-localhost.ctl -O exit firewall.company.com
posted at: Tue, 04 Mar 2008 21:51 | in /linux/tips | permalink | add comment (0 others)
Last night, after dropping a package from a control file, I was wondering why my package.install file for the remaining package seemed to be ignored (upstream installs a bunch of stuff that I don't want installed in the Debian package; the symptom was all that junk was making its way into the package). Turns out it comes down to the following logic in CDBS:
ifeq ($(words $(DEB_ALL_PACKAGES)),1)
DEB_DESTDIR = $(CURDIR)/debian/$(strip $(DEB_ALL_PACKAGES))/
else
DEB_DESTDIR = $(CURDIR)/debian/tmp/
endif
i.e. if there is only one package, then by default install in debian/package. Therefore whatever make install does is what you end up with in your package. Although I can see the reasoning behind this, it wasn't what I wanted since I need the package installed into a temporary location (i.e. debian/tmp) which then uses a .install file to pull out only those files I want. The solution is simple, override DEB_DESTDIR to $(CURDIR)/debian/tmp/ in rules.
I hope this saves someone the half hour or so I spent investigating why my install file was "corrupt"!
posted at: Tue, 05 Feb 2008 15:30 | in /linux/debian | permalink | add comment (0 others)
Or, a modern guide to CPU frequency scaling with Linux. Having setup my laptop long ago, I had a strange hybrid of daemons running all trying to scale the frequency of my laptop periodically based on a myriad of different situations. Having decided to fix this, it appears the simplest approach is, as usual, the best.
The way of the future appears to be to let the kernel do all the work with the ondemand govener. The cpufrequtils Debian package will arrange this for you on boot and by default should just work, although you can of course tweak parameters like minimum speed to decrease to and so forth. You can use the cpufreq-set utility to fiddle with settings, or just go into /sys/devices/system/cpu/cpuN/cpufreq/ to tweak them by hand. The many available daemons (cpufreqd, powernowd, etc.) appear to be largely redundant and are probably best removed.
This dropped the temperature of my laptop about 10 degrees C and, apart from a much cooler lap, is so far imperceptible.
posted at: Tue, 29 Jan 2008 16:30 | in /linux/tips | permalink | add comment (0 others)

This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.