Pretty accurate instructions, for today…
2 months ago
Pretty accurate instructions, for today…
2 months agoI recently received an invoice for a domain renewal from 1and1.com — however, I never asked for the domain to be renewed, nor had any expectation that it would be. In fact, when I first purchased the domain, I specifically was purchasing it for a single year and didn’t get the impression that my billing information would be stored on their servers.
I’ll freely admit that they sent an email about a month and a half ago that said they’d be auto-renewing the domain. However, the subject was “1&1 domain renewal notification,” and glancing at it, I read “The domains listed below are due to expire in 42 days on [date].” Since I knew I had not requested an automatic renewal I simply ignored the email so that the domain would expire.
So anyway, I called ‘em up and asked about it, and they said they could send a link to a refund/cancel form. Which of course I assumed would be an online form behind secure authentication that would let me simply take care of it all. Instead, it was a link to a PDF that I was supposed to fill out and mail or fax in. And they wanted my account information, credit card information, and a copy of a government-issued photo ID. So considering that I already lost all trust in the company due to the way they charged me for a renewal and stored my billing info without me realizing it, there’s certainly no way I would send them all that information together, especially in a completely insecure manner. (Later another customer support representative told me he doesn’t believe the copy of the ID is necessary, but the form says you have to include it.)
The second customer support representative I talked to put me on hold and transferred me to the cancellations department without asking me first — “I’ll have to transfer you to cancellations [click]”… Talking to someone in cancellations (who of course says they have no ability to deal with refunds), she actually asked me to verify my password for her over the phone. I wasn’t about to do that, but it decreased my trust of them even further.
So having hit complete dead-ends with their customer support folks, who say that I agreed in the first place to auto-renewal, and that they can’t refund the charge without me mailing/faxing that form, I gave up and decided to just cancel my account, eating the $9 for the renewal. (Side note: the first year was $7 — having it auto-renew at a higher rate is one more reason I don’t trust them.) Unfortunately, when I requested that they delete all my personal, private billing information from their servers after I cancel (because they have no right to store it without my consent), the representative told me that it’s not possible to delete such information from their system. (!!!)
The only way to cancel the account is to look up in their FAQ that you go to cancel.1and1.com to process cancellations, which I did. Of course, then, it makes you go through an email verification (sending a link in email) to verify the cancellation. However it also says that they won’t process your cancellation until you print, sign, and mail/fax another form to them (albeit a simpler one than the refund form). I have a hard time believing they stay in business, except for all the charges they receive from people who didn’t want an auto-renew, and haven’t gone through the ordeal of cancelling.
So, if you’re thinking of buying a domain from 1and1.com, make sure you read all the fine print, and make sure you really want it to auto-renew (at whatever rate they decide is appropriate for subsequent years), and be prepared for some hassle if you ever want to cancel your account.
5 months ago
Little-known unix command: complete
At least for the bash shell, this command controls the programmable tab-completion, allowing you to configure certain programs so their tab-completion only matches files, dirs, some arbitrary set of terms, etc.
A common example is to set up “svn” so that bash knows its commands, and tab-completes them for you. A very simplistic version would be like the following:
complete -W "add blame checkout commit copy delete diff log revert status switch update" svn
Granted, for brevity I left out a lot of commands, including their shortened versions, etc. However it turns out it’s pretty cool, because then you can type “svn u” and hit tab, and suddenly it’s got “svn update” in there for you, rather than trying to match filenames.
Of course, that brings up an interesting issue — you probably want to match a directory or filename for the second argument… And if you want to get crazy, complete lets you do that by passing it a shell function that returns possible completions for the current situation. There’s a whole package out there with specialized functions for common unix commands, which you can find at http://www.caliban.org/bash/.
However, this blog post is about abusing the tab-completion to match certain domain names. Existing EC2 instances, that is. At work we use DynDns to provide a dynamic domain name to each of our EC2 instances, and of course we often want to ssh into them by the dynamic names rather than the default Amazon ones, which look like “ec2-67-123-123-123.compute-1.amazonaws.com”. For that, first of all, we need to figure out which domain names are currently being used by instances.
That’s done with a combination of parsing IP addresses out of the data returned from ec2-describe-instances, and looking up the current IP addresses of each of our dynamic domain names. The ec2 IP parsing looks kinda’ like this (in Ruby):
running_ips = []
`ec2-describe-instances`.each_line { |line|
running_ips << $1.gsub('-','.') if line =~ /\bec2-([0-9-]+)/
}
The domain lookup is only marginally more complicated…
domains = ("001".."010").collect { |n| "server-#{n}.example.com" }
domain_lookup = {}
`dig #{domains.join(' ')}`.each_line { |line|
domain_lookup[$2] = $1 if line =~ /^\s*(server-\d+\.example\.com).+?\s+IN\s+A\s+([\d.]+)/
}
And then we can get a list of currently running domains by pulling the relevant slice of IPs from domain_lookup, and excluding any nils:
running_domains = domain_lookup.values_at(*running_ips).compact
Printing that out looks something like this:
>> puts running_domains.join(' ')
server-001.example.com server-002.example.com server-004.example.com
So … Coming back to the bash completion, we could put all that in a script and then do something of this sort:
complete -W '$(ruby ec2_domain_lookup.rb)' ssh
But of course, that’d limit ssh’s tab-completion to only these servers, and would leave out useful things like the username, etc. Helping that, however is the fact that I’ve already got two aliases in my profile for working with ec2 boxes:
alias ec2='ssh -i ~/.ec2/ssh-keypair -o StrictHostKeyChecking=no -o ServerAliveInterval=240 -l root'
alias escp='scp -i ~/.ec2/ssh-keypair -o User=root'
These let me connect to an ec2 box with “ec2 hostname” or scp files to it with “escp file hostname:” (assuming you get the path to your keypair correct, etc.)
So coming back to the tab-completion, we finally get this:
complete -W '$(ruby ec2_domain_lookup.rb)' ec2
And then since the escp command should also include directories and filenames in its completion, we use the following for it:
complete -W '$(ruby ec2_domain_lookup.rb)' -d -f escp
So that’s the basics… The next step is to set it up so you always have those available in your shell, and don’t have to wait 10-15 seconds for all the IP/domain lookups to complete, as it generates the completion lists. So I have a cron job that periodically runs the lookup script, and outputs a file with the two complete commands in it. My .bash_login script just sources the file like so:
. ~/.ec2_tab_completion_commands
And it’s always available without delays. Enjoy. :)
Google Labs Gmail features are finally integrated into Google Apps for your Domain accounts! Yay! Yay!
1 year agoRelated to the earlier post on doing backtraces, I figured out how to make some portions work on the Mac version of ruby and/or gdb, so you can do it even when you can’t easily capture stdout…
$ gdb -p <process_id>
call (int)rb_eval_string(“$_old_stdout, $stdout = $stdout, File.open(‘/tmp/ruby-debug.’ + Process.pid.to_s, ‘a’); $stdout.sync = true”)
call (int)rb_eval_string(“puts caller.join(\”\\n\”)”)
Yay. Now it’ll throw the backtrace into a file in your tmp dir. I’m assuming the same would still work on linux or other unix variants, too.
1 year agoWe all know that laptop batteries lose some of their capacity over time. Apple generally warrants them for a year, if I remember correctly, but after that you’re on your own if the battery barely holds a charge. But how do you get real info on your battery, other than doing time comparisons?
Luckily the Mac provides some fairly detailed info. There’s an application called coconutBattery that will display this for you, but personally I prefer to grab it from the command line (the same way coconutBattery gets its info).
I have an alias set up, called “battery”:
$ alias battery=’ioreg -w0 -l | grep Capacity | cut -d ” ” -f 17-50’
This just sets it up so when you type “battery”, it asks the mac to list off a bunch of info and looks for the lines talking about “Capacity” (and then strips off some extra whitespace).
So here are two examples, from different batteries:
$ battery
“CurrentCapacity” = 4388
“LegacyBatteryInfo” = {“Capacity”=4388,”Voltage”=12583,”Flags”=5,”Current”=4388,”Amperage”=131,”Cycle Count”=152}
“DesignCapacity” = 5500
“MaxCapacity” = 4388
$ battery
“CurrentCapacity” = 1608
“LegacyBatteryInfo” = {“Capacity”=1925,”Voltage”=12260,”Flags”=7,”Current”=1608,”Amperage”=12,”Cycle Count”=102}
“DesignCapacity” = 5500
“MaxCapacity” = 1925
Basically this shows the current capacity (charge), max capacity, and the capacity the battery was designed for. The LegacyBatteryInfo line has some other useful info, like flags that tell whether the power cord is plugged in, if the battery is currently charging, and the number of complete recharge cycles the battery has effectively been through.
What’s interesting here is to see that the first battery is still doing pretty well — it currently can store about 80% of its original charge (4388/5500). That’s after 152 cycles (and approximately a year of use). The other battery is a pathetic example, which holds 35% of what it originally could have, after only 102 cycles (and being used less than the other battery over the course of the year). Personally I’d call it a manufacturing defect, but unfortunately being a bit more than a year old, Apple won’t take responsibility for it.
Mallards Game
1 year ago