Friday, January 25, 2008

sudo: /etc/sudoers is owned by

Right about now you're probably looking at somthing similar to this.
sudo: /etc/sudoers is owned by gid 1000, should be 0

Maybe you accidently chown'd or chmod'd files recursively where the etc directory was effected. Maybe you did the same thing I did & chowned /etc/sudoers to root:mygroup instead of root:root like it's supposed to be.

In any event you're looking at a message like the one above and you can't use sudo anymore. This is because the sudo application wants things exactly right or it assumes there's been a compromise.
The file /etc/sudoers should be owned by root:root and should not be readable by anyone other than root.

Unless for some reason you allow remote root logins, you will need to physically have the server in front of you to fix this issue. If you don't have a monitor hooked up to the system, you better find a monitor to hookup now.

If you have the root password, login as root & chown the file to root:root.
root@box:~$ chown root:root /etc/sudoers

Then chmod the /etc/sudoers to 0440.
root@box:~$ chmod 0440 /etc/sudoers

If you, like I, never set a root password, you'll need to reboot the system, press ESC during boot, & select the recovery mode from the boot options. That will give you a terminal logged in as root you can use to run the chown and chmod commands.

Once the proper ownership & permissions are set on that file you can restart the system as usual & sudo should be up and running again.

Saturday, January 12, 2008

Fancy Blogger Labels Widget

I just noticed Blogger has a post labels widget the other day. After adding it to my layout I discovered I was using quite a few one-time-use labels for my posts. I spent a little while going through my labels & trying to consolidate some of the one-timers into better upper-level groups.
Even after doing this there was still a huge list of words running down the right side of the layout, and I really didn't like how that worked.

So, I fixed it.

With the widget added to my layout, I then modified the HTML used so it was a little cleaner as well as matching the rest of the layout. Blogger templates seem to like using <h2> elements for sidebar items and I like to use <h6> elements.

<b:widget id='Label1' locked='false' title='By Subject' type='Label'>
<b:includable id='main'>
<span class='top'><span/></span>
<div class='content' id='by-subject'>
<b:if cond='data:title'><h6><data:title/></h6></b:if>
<ul><b:loop values='data:labels' var='label'><li><b:if cond='data:blog.url == data:label.url'><><b:else/><a expr:href='data:label.url'><></a></b:if> <small><data:label.count/></small></li></b:loop></ul>
<span class='bottom'><span/></span>

With that, I have a clean matching list of labels in the event JS is disabled.

Now for the fancy part.
I'm having jQuery split that list up into smaller lists, much like the Last 50 Posts navigation works with the dates.
Here's the JS I'm using to do that, note that it's among the things that happen after the document has loaded.
var tags = $('<ul/>');
var branch;
var label = {start:'', end:''};
var tagIndex = 0;
$('#by-subject li').each(function(){
label.end = $(this).children('a').text().toLowerCase();
case 1:
branch = $('<ul/>');
label.start = label.end;
case 10:
tagIndex = 0;
var at = $('<li><a href="#">(' + label.start + ') -- (' + label.end + ')</a></li>');
return false;
var at = $('<li><a href="#">(' + label.start + ') -- (' + label.end + ')</a></li>');
return false;
$('#by-subject ul').replaceWith(tags);

Basicly, the list is split up into sections of 10 items & each section is labeled with the first and last items in each section. I'll probably switch it to 20 items sometime in the future.

Tuesday, January 8, 2008

Javascript Random Ad Buttons/Banners

I like to think of ad banners on my blog like like the racks in the checkout lines at the grocery store, Impulse Items. I wanted to be as un-obtrusive as possible with ad banners, while still having them stand out.

In order to do this I'm using JS to display them. That way I can defer them from showing untill the content people have come here from search engines to read in the first place has already loaded.
I absolutely hate it when a site makes me stare at a blank section where the article would be while I wait for the advertisements to load. If there's another result I considered clicking on I will immediately close the tab with that blank section in it & go with the alternative instead.
I also don't want to go out of my way to force people to look at advertisements by bypassing blockers & such, doing so appears to be a waste of time.

Now that we know I don't want to intrude, but do want to nag you a little bit, here's how I'm doing it.

First I have an array with objects for all of my banners. Each object includes the alt, href, and src attributes I will need for each banner. Though for some odd reason I decided to use url to denote my href attributes here.
var impulses = new Array(
{alt:'image alt text', url:'click-through-url', src:'image-source'},
{alt:'image alt text', url:'click-through-url', src:'image-source'},
{alt:'image alt text', url:'click-through-url', src:'image-source'}

For the sake of simplicity there's only three in that example, but just imagine there's about twenty of those objects in that array.

Now since I don't want the order they're shown in from left to right to be too predictable I'm going cycle a random number of ad banner objects to the end.
Basicly what this code is doing, is geting a random number between zero and the number of ad banner objects there are in the impulses array, and moving the first ad banner object to the end of the array that many times.
for(var i = Math.round(Math.random() * impulses.length); i > 0; i--)

Next I narrow the size of the array down to the number of ad banners I want shown.
Basicly what this code is doing is randomly picking an ad banner object in the array and removing it, untill there's only as many as I want left.
while(impulses.length > 5)
impulses.splice(Math.round(Math.random() * (impulses.length - 1)), 1);

Once the ad banners that will be displayed are determined I generate the HTML to show them with, I'm using simple <a> and <img> elements for this. I like to generate it using basic data like this so it's easier to modify the actual HTML that's used in a single place later on if I need to.
for(var i = 0; i < impulses.length; i++)
impulses[i] = '<a href="'+impulses[i].url+'"><img alt="'+impulses[i].alt+'" src="'+impulses[i].src+'"/></a>';

Now with a string of ad banner HTML to use, I make use of the jQuery library to insert it amongst my pages.
var impulse = jQuery("<div id='impulses'>" + impulses.join('') + "</div>").insertBefore('#load-anim');