nix, shell, perl, php, mysql and mac os x tips and tricks

Friday, January 13, 2012

Fix for Postfix mail issue after upgrading from OS X 10.6 to 10.7

Postfix stops working. It throws errors like:
Jan 13 12:18:52 huggybunny postfix/master[2254]: warning: process /usr/libexec/postfix/smtp pid 2299 exit status 1
Jan 13 12:18:52 huggybunny postfix/master[2254]: warning: /usr/libexec/postfix/smtp: bad command startup -- throttling

I had it set up to replay through GMail. Looks like the /etc/postfix/sasl_password file was deleted during the upgrade. All I had to do was create it again per these instructions, reload postfix and it was good to go.

UPDATE: that link appears to have disappeared. Here's what you do:

Gmail Email Relay using Postfix on Mac OS X 10.5 Leopard


I use Postfix to relay system messages (e.g. a botched cronjob) over SSL to my Gmail account. These messages are otherwise “lost” because the email is being sent to a dormant mail transfer agent on my Mac. There’s way more that you can do with Postfix, but I’ll just cover the setup I did for my needs.

1. Create the Simple Authentication and Security Layer (SASL) password file.

sudo vi /etc/postfix/sasl_passwd

Enter and save the following

smtp.gmail.com:587 your.name@gmail.com:your.password
2. Create a Postfix lookup table for SASL.

sudo postmap /etc/postfix/sasl_passwd

3. Configure Postfix with

sudo vi /etc/postfix/main.cf

By default, everything is commented out. You can just append this to the end of file and save:

# Minimum Postfix-specific configurations.
mydomain_fallback = localhost
mail_owner = _postfix
setgid_group = _postdrop
relayhost=smtp.gmail.com:587
# Enable SASL authentication in the Postfix SMTP client.
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options=

# Enable Transport Layer Security (TLS), i.e. SSL.
smtp_use_tls=yes
smtp_tls_security_level=encrypt
tls_random_source=dev:/dev/urandom

5. Start postfix with

sudo postfix start

If you get an error, address the parameter in main.cf that is in the error and use

sudo postfix reload

to refesh Postfix. If everything looks good, then send an email

date | mail -s test your.name@gmail.com

If you don’t get an email fairly quickly, enter

mailq

and you should see the email there along with a description of any problems. If the mail is not in the queue, you most likely got something wrong in main.cf so you’ll need to do some debugging. If your mail queue starts to fill up during this process, you can clear it with

sudo postsuper -d ALL

6. Once you have everything working, you can set Postfix to start on boot by adding a key to /System/Library/ LaunchDaemons/org.postfix.master.plist. If you have Property List Editor (or something similar), you can add the key RunAtLoad of type Boolean with a value that is checked.

Alternatively,

sudo vi /System/Library/LaunchDaemons/org.postfix.master.plist

and add the following just before the tag

RunAtLoad

Empty the Postfix mail queue

Deletes everything.
sudo postsuper -d ALL

Tuesday, January 3, 2012

Running Parallels 5 or 6 after upgrading to Mac OS X Lion (10.7)

Naturally, Parallels doesn't work after upgrading. It will show you an error like "Unable to load the Parallels Driver. Please restart your mac and try again." when you try to start a virtual machine. They are relentless about keeping you on the teat of their upgrades. Just like Intuit.

Anyway, I found a workaround. All I can say is that it worked for me. Don't blame me if it blows up your computer. I am doing this as "root" user rather than sudo-ing. Run these commands and it should start.
chgrp -R wheel "/Library/Parallels/Parallels Service.app/Contents/Kexts/10.6/";
sudo kextutil "/Library/Parallels/Parallels Service.app/Contents/Kexts/10.6/prl_hypervisor.kext";
sudo kextutil "/Library/Parallels/Parallels Service.app/Contents/Kexts/10.6/prl_hid_hook.kext";
sudo kextutil "/Library/Parallels/Parallels Service.app/Contents/Kexts/10.6/prl_usb_connect.kext";
sudo kextutil "/Library/Parallels/Parallels Service.app/Contents/Kexts/10.6/prl_netbridge.kext";
sudo kextutil "/Library/Parallels/Parallels Service.app/Contents/Kexts/10.6/prl_vnic.kext";

So, after that, you might (i.e. will probably) need to run this "Parallels Desktop Launcher" script. Perhaps even every time you run parallels (you could just replace the icon in your dock I suppose)

Launcher

When the Mac App store hangs on connection (10.6 or later)

  1. Close App Store and iTunes completly (blue circle under each should disappear)
  2. Open Terminal (Applications -> Utilities -> Terminal)
  3. Run the following:
    mv -f ~/Library/Preferences/com.apple.storeagent.plist ~/Library/Preferences/com.apple.storeagent.old.plist
    mv -f ~/Library/Preferences/com.apple.appstore.plist ~/Library/Preferences/com.apple.appstore.old.plist
    
  4. This will reset a number of preferences about the App Store.
  5. Restart your Mac! - This is key!
  6. Open App Store. you'll need to re-login

Wednesday, December 28, 2011

Setting a specific proxy for Google Chrome

Like Safari, Google Chrome uses OS-level proxy settings. But what if you need your browser on a different proxy? Answer: you can pass proxy info to Chrome by opening it on the command line like this:
open -a /Applications/Google\ Chrome.app --args --proxy-server=[host]:[port]
And if you want the convenience of launching from your dock, create a wrapper script and icon using one of these methods (copied from here because it's a flaky link):

Option 1: Use Automator to create an application that in effect launches Chrome with command line arguments.

Start Automator and select to create an Application. Double-click Run Shell Script in the Library/Utilities folder and replace the text content — cat — with the following:
open -a /Applications/Google\ Chrome.app --args --proxy-server=[host]:[port]
Save anywhere you like.

To replace this application's icon, Get Info on your real Google Chrome, click on the icon on the top left, press Cmd-C, Get Info on your Chrome Automator app, click the icon, and press Cmd-V.

Since it's a different application, the Dock will display two Chrome applications when it's running: Chrome, and your Chrome launcher.


Option 2: Edit your application bundle to launch a script instead. This script will start the actual application, adding the command line argument.

Right-click Google Chrome.app and select Show Package Contents. Go to Contents/ and open Info.plist in Property List Editor/Xcode (Apple's developer tools), or a third party plist editor.

Look for the entry CFBundleExecutable or Executable File. Remember its value (e.g. firefox-bin for Firefox). Replace it with parameterized-app.sh.

Open Terminal and enter the following:
touch /Applications/Firefox.app/Contents/MacOS/parameterized-app.sh
open /Applications/Firefox.app/Contents/MacOS/parameterized-app.sh

An editor for the .sh file will open. Set the contents of the file to:
#!/usr/bin/env bash
/Applications/Firefox.app/Contents/MacOS/firefox-bin -ProfileManager

(using the actual executable's name you removed from Info.plist, adding the desired command-line arguments)

Save and close. In Terminal, enter the following:
chmod +x /Applications/Firefox.app/Contents/MacOS/parameterized-app.sh

Now, close Terminal and move your application (which must not be running right now) to a different folder and back again. This will update Launch Services, otherwise your changes will be ignored and irritate you immensely.

Now, when you open your application, it will actually execute the .sh file, which will in turn launch the actual executable file, sending the command line args along.

It will look and behave like you expect it to, but you will need to repeat this whenever you update your application, as this will generally replace the application bundle and all the changes you made.

Friday, October 28, 2011

Shell Script to re-name file extensions

OLDEXT=${2/#.}
for file in *.jpg ; do mv $file `echo $file | sed 's/\(.*\.\)jpg/\1png/'` ; done

Monday, July 18, 2011

Remove multiple instances of a character (or a pattern) from a URL, then do a 301 redirect, with mod_rewrite

There was actually some html tags appearing in some of my URLs. This hack strips tags and does a search-engine-friendly redirect.
RewriteCond %{REQUEST_URI} ^(.*)<.*?>(.*)$
RewriteRule ^.*$ %1%2 [E=replacer:%1%2]
RewriteCond %{ENV:replacer} !^$
RewriteCond %{ENV:replacer} !^.*<.*?>.*$
RewriteRule ^.*$ %{ENV:replacer} [R=301,L]

This part matches the tags: "<.*?>". Replace that with your character or pattern.

Thursday, July 14, 2011

Check line endings of a file from command line

type 'od -c [filename]' and look for either \n (indicating LF) or \r \n (indicating CRLF)

Search bash history

Not sure why I never new this, but hitting ^r in bash will put you into history search mode. Type the beginning of the command, then just keep hitting ^R to go back in history. Helps when you want to find a long command that you entered previously.

Friday, July 1, 2011

grep pattern to match e-mail address

grep -Eiorh '([[:alnum:]_.]+@[[:alnum:]_]+?\.[[:alpha:].]{2,6})' file.txt

Tuesday, February 1, 2011

Workaround for Snow Leopard (10.6) issue with osascript command

If you see this bizarre error when using the osascript command:
2011-02-01 14:11:28.727 osascript[11990:903] Error loading /Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types:  dlopen(/Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types, 262): no suitable image found.  Did find:
        /Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types: no matching architecture in universal wrapper
it apparently has to do with the mixing of 32 and 64-bit architectures. I don't know what the real fix is, but the workaround is to force osascript to use 32-bit like this:
arch -i386 /usr/bin/osascript -e '[your applescript]'

Thursday, December 2, 2010

Strip leading zeroes using regex

Doesn't actually "strip", rather captures the non-laeding-zero number. Works only on a string that only contains numbers, and is compatible with ancient regex versions.
^[0]+([1-9][0-9]{1,})$
NOTE: will NOT match a number that doesn't have leading zeroes

Saturday, October 9, 2010

Neat MySQL SUBSTRING Functions

Chop off the first character of a string that matches a particular regex pattern:
SELECT SKUID, CATEGORY, SUBSTRING(CATEGORY,2) FROM products WHERE CATEGORY RLIKE '^;([0-9;]{1,20});$'

Chop off the last character of a string
SELECT SUBSTRING(CATEGORY,1,LENGTH(CATEGORY)-1) AS CATEGORY FROM products WHERE CATEGORY RLIKE '^([0-9;]{1,20});$';

Extract the domain name (including subdomain) from an URL:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(url,'://',-1),'/',1) FROM urls

Monday, October 4, 2010

Recursively delete old directories

careful with this one!
/usr/bin/find /home/user/oldlogs/ -maxdepth 1 -type d -mtime +90 -exec rm -rf {} \;

Wednesday, September 22, 2010

Use 'find' to recursively chmod files

another 'find' quickie...
find /home/user/files/ -name 'myfile.sh' -exec chmod 755 {} \;

Thursday, September 16, 2010

Capitalize the first letter of a sentence with MYSQL

UPDATE `categories` SET category_name = CONCAT(UCASE(SUBSTRING(`category_name`, 1,1)),LOWER(SUBSTRING(`category_name`, 2)))

Monday, June 14, 2010

MySQL function for replacing HTML entities with their actual characters

For a more comprehensive function containing more special characters see http://forums.mysql.com/read.php?98,246527

Actually, better use that link (above). Blogger is messing with the code below.

Usage:
SELECT HTML_UnEncode(firstname),HTML_UnEncode(lastname) FROM users;

DELIMITER $$

DROP FUNCTION IF EXISTS `sourcedatabase`.`HTML_UnEncode`$$
CREATE DEFINER=`user`@`localhost` FUNCTION `HTML_UnEncode`(x VARCHAR(255)) RETURNS varchar(255) CHARSET latin1
BEGIN

DECLARE TextString VARCHAR(255) ;
SET TextString = x ;

#quotation mark
IF INSTR( x , '"' )
THEN SET TextString = REPLACE(TextString, '"','"') ;
END IF ;

#apostrophe 
IF INSTR( x , ''' )
THEN SET TextString = REPLACE(TextString, ''','"') ;
END IF ;

#ampersand
IF INSTR( x , '&' )
THEN SET TextString = REPLACE(TextString, '&','&') ;
END IF ;

#less-than
IF INSTR( x , '<' )
THEN SET TextString = REPLACE(TextString, '<','<') ;
END IF ;

#greater-than
IF INSTR( x , '>' )
THEN SET TextString = REPLACE(TextString, '>','>') ;
END IF ;

#non-breaking space
IF INSTR( x , ' ' )
THEN SET TextString = REPLACE(TextString, ' ',' ') ;
END IF ;

RETURN TextString ;

END$$

DELIMITER ;

Tuesday, June 8, 2010

Find duplicate records in MySQL

SELECT email, 
 COUNT(email) AS NumOccurrences
FROM users
GROUP BY email
HAVING ( COUNT(email) > 1 )

Thursday, May 20, 2010

sed one-liner for removing HTML tags from a file

sed -e 's/<[^>]*>//g' myfile.html

Monday, May 10, 2010