Archive for May, 2008

List last running status of enabled jobs in Sql Server

Script below. This one works better for Sql Server 2000. I will do a version for Sql Server 2005, when I get a chance. It didn’t work very well on Sql Server 2005 because Ad Hoc Distributed Queries is disabled by default.

set nocount on
IF OBJECT_ID(’tempdb..#TmpJobs’) IS NOT NULL
DROP TABLE #TmpJobs

SELECT *
INTO #TmpJobs
FROM OPENROWSET(’sqloledb’
, ’server=(local);trusted_connection=yes’
, ’set fmtonly off exec msdb.dbo.sp_help_job @enabled = 1′)

select ‘Successful run’

SELECT cast(name as varchar(59)),
LastRunDatetime = CASE last_run_date
WHEN 0 THEN ‘Never’
ELSE
CONVERT(varchar(10), CONVERT(smalldatetime, CAST(last_run_date as varchar), 120), 120)+’ ‘+
RIGHT(’0′+CAST((last_run_time/10000) AS VARCHAR), 2)+’:'+
RIGHT(’0′+CAST((last_run_time-((last_run_time/10000)*10000))/100 AS VARCHAR), 2)+’:'+
RIGHT(’0′+CAST((last_run_time-((last_run_time/10000)*10000)-((last_run_time-((last_run_time/10000)*10000))/100*100)) AS VARCHAR), 2)
END
FROM #TmpJobs where last_run_outcome = 1

select ‘Failed run’

SELECT cast(name as varchar(59)),
LastRunDatetime = CASE last_run_date
WHEN 0 THEN ‘Never’
ELSE
CONVERT(varchar(10), CONVERT(smalldatetime, CAST(last_run_date as varchar), 120), 120)+’ ‘+
RIGHT(’0′+CAST((last_run_time/10000) AS VARCHAR), 2)+’:'+
RIGHT(’0′+CAST((last_run_time-((last_run_time/10000)*10000))/100 AS VARCHAR), 2)+’:'+
RIGHT(’0′+CAST((last_run_time-((last_run_time/10000)*10000)-((last_run_time-((last_run_time/10000)*10000))/100*100)) AS VARCHAR), 2)
END
FROM #TmpJobs where last_run_outcome = 0

Comments

List all sa sysadmin in your Sql Server instances with Perl

This is mainly for my own reference. Save it as ListSysadmin.pl. Run ListSysadmin.pl SqlServerList.txt on command line. It lists all logins that has sa (sysadmin) rights on Sql Server instance, including individual domain members in a domain group that has sysadmin rights.

SqlServerList.txt should be a text file, with each individual line contains a Sql Server instance.

This script is an improvement over Linchi’s original scrip from his Real World SQL Server Administration with Perl. The original script only takes one instance as input parameter. Note: with my current site style sheet on my web site, I think it ignores the angle brackets, so you need to fix the script when you do copy and paste.

use strict;
use Win32::ODBC;

# Import the function from the module SQLDBA::Utility
use SQLDBA::Utility qw( dbaRemoveDuplicates );

# Import functions from the module Win32::NetAdmin
use Win32::NetAdmin qw( GetDomainController
GroupGetMembers
LocalGroupGetMembersWithDomain
UsersExist );

Main: {
my $log = shift or die “***Err: $0 expects a file name.\n”;
open(LOG, “$log”) or die “***Err: couldn’t open $log.\n”;
while () {
my $line = $_;
if ($line =~ /\[?(\w+)/ix) {
my $serverConn = $1;

print "Instance: $1\n";

# get all the accounts/logins with sysadmin role from SQL Server
my $loginRef = getSQLSysadmins($serverConn);
# in case the server name is followed by an instance name
my ($server) = $serverConn =~ /([^\\]+)(\\.+)?/;

# replace BUILTIN with the server name
foreach (@{$loginRef->{groupSet}}) {
s/BUILTIN\\/uc($server) . “\\”/e; # evaluate the right side before replace
}

# remove all local groups and get their members
$loginRef = removeLocalGroups($loginRef);

# get global group members
$loginRef = getGlobalGroupMembers($loginRef);

# now print out all the NT/SQL logins that are SQL sysadmin
print “Listing all NT/SQL logins with the sysadmin rights …\n”;
foreach (sort @{$loginRef->{resultSet}}) { print “\t$_\n”; }
}
}
close(LOG);

} # Main

#########################
sub getSQLSysadmins {
my $serverConn = shift or
die “***Err: getSQLSysadmins() expects a server.”;

my $connStr = “Driver={SQL Server};Server=$serverConn;” .
“Trusted_Connection=Yes;Database=master”;
my $conn = new Win32::ODBC ($connStr) or
die “***Err: Can’t connect to $serverConn. ” . Win32::ODBC::Error();

# get sysadmin logins (NT and SQL)
my @logins = ();
my $sql = q/SELECT loginname FROM master.dbo.syslogins
WHERE sysadmin = 1
AND isntgroup = 0/;

unless ($conn->Sql( $sql )) {
@logins = (@logins, $conn->Data) while ($conn->FetchRow());
} else {
print “***Err: executing $sql. “, Win32::ODBC::Error(), “\n”;
}

# get sysadmin nt groups
my @groups = ();
my $sql = q/select loginname from master.dbo.syslogins
where sysadmin = 1
and isntgroup = 1/;

unless ($conn->Sql( $sql )) {
@groups = (@groups, $conn->Data) while ($conn->FetchRow());
} else {
print “***Err: executing $sql. “, Win32::ODBC::Error(), “\n”;
}
$conn->Close();

return { resultSet => \@logins,
groupSet => \@groups,
userSet => undef };
} # getSQLSysadmins

###########################
sub removeLocalGroups {
my $loginRef = shift or
die “***Err: removeLocalGroups() expects a reference.”;

foreach my $group (@{$loginRef->{groupSet}}) {
if (my $rc = getLocalGroupMembers($group)) {
push @{$loginRef->{userSet}}, @{$rc};
}
else {
push @{$loginRef->{userSet}}, $group;
}
}
delete $loginRef->{groupSet};
return $loginRef;
} # removeLocalGroups

##############################
sub getGlobalGroupMembers {
my $loginRef = shift or
die “***Err: getGlobalGroupMembers() expects a reference.\n”;
my @logins = ();

foreach my $user (@{$loginRef->{userSet}}) {
if ($user =~ /^NT\s+AUTHORITY\\/) {
push @logins, $user;
next;
}

my ($domain, $name) = $user =~ /^(.+?)\\(.+)$/;
if ( UsersExist($domain, $name ) ) { # a user account
push @logins, $user;
}
else {
my $pdc;
my @users;
if (GetDomainController(undef, $domain, $pdc)) {
$pdc =~ s/\\//g;

if ( UsersExist($pdc, $name ) ) {
push @logins, $user;
}
else { # $name is a global group account
# get users in the global group
if (GroupGetMembers($pdc, $name, \@users)) {
# prefix the users with the domain name
push @logins, map { “$domain\\$_”; } @users;
}
else { # you shouldn’t reach here
print “***Err: can’t retrieve users for $domain\\$name.\n”;
next;
}
}
}
else {
print “***Err: can’t find domain controller for $domain.\n”;
next;
}
}
}

push @logins, @{$loginRef->{resultSet}};
$loginRef->{resultSet} = dbaRemoveDuplicates(\@logins);
return $loginRef;
} # getGlobalGroupMembers

################################
sub getLocalGroupMembers {
my $group = shift or
die “***Err: getLocalGroupMember() expects a group name.”;

my ($domain, $group_name) = $group =~ /^(.+?)\\(.+)$/ or
die “***Err: $group must be qualified with a domain/machine name.”;

my @users = ();
if (LocalGroupGetMembersWithDomain($domain, $group_name, \@users)) {
return \@users;
}
else {
return undef;
}
} # getLocalGroupMembers

Comments (2)

捐款不在多少

和大家一样,我最近读了很多关于地震救灾的消息,很为那么多人的奉献和爱心所感动。

也读到了关于捐款的新闻。其中还有不同版本、不同行业的“铁公鸡”排行榜。很多人还为谁捐多少、该捐多少争得脸红脖子粗,骂人的、扣帽子的话都出来了。个人观点:捐款不是作秀,不是攀比,不在多少。所以我和王建硕在这个问题上很有同感。当然不排除对一些名人、奸商的伪善进行揭露和批评,但出口伤人,以为嗓门大就有理就不对了。

还读了不少关于砂轮斯通的新闻。这个过气女星的评论当然很可气,值得一驳。但看到举国上下的声讨,是不是有点忒那个了。有点高射炮打蚊子的感觉。可能媒体的炒作也有推波助澜的作用。

以下是我在王建硕的博客的评论,记录过来。

You struck a chord with me on this one, Jian Shuo.

I am with you regarding the “donation competition and condemnation”. I am sick of it myself.

I don’t know what other popular public opinion troubles you. One thing that I personally felt a little uncomfortable with was the over reaction seemingly from so many people against Sharon Stone’s comments, not that I condone her obnoxious and ignorant activities. To me, she is just one of Hollywood has-been. Total indignation from so many people to such a pathetic, attention-seeking has-been do not reflect well on the former.

Somethings change quickly, others do not. It is what it is. Cheer up and speak up in a respectful way. Things will get better, slowly but surely.

Comments (1)

When was the last time a full backup was taken

One of the first things you want to do as a DBA is to check when was the last time a full backup was taken for all databases you manage. For Sql Server, here is a script you can run:

set nocount on
select cast(a.name as char(30)), max(b.backup_finish_date) from master..sysdatabases a left outer join msdb..backupset b on a.name = b.database_name
where a.name not in (’model’, ‘tempdb’, ‘pubs’, ‘northwind’, ‘adventureworks’)
group by a.name

Suppose we have a list of instances we manage, I cannot emphasize enough how convenient it is to be able to blast the above statement to all instances we manage. That way we get all full backup information on all instances in one fell swoop. Fortunately, Linchi Shea wrote a couple of utilities just for that: one in C#, one in Perl. Check ‘em out here.

Comments

和你在一起

I am in Florida with the family on vacation, and put myself in web-free mode last Sunday.

Tuesday afternoon, as an older gentleman was helping us getting to our car, I commented on his New York accent. He said he had left his native NYC for a long time, and has been to many places, but didn’t seem to lose his accent. I told him that I will never lose my dialect either, though I speak good Putonghua, and can even occasionally pose as a native Beijinger. It was at that time that he told me that there was a big earthquake in Chengdu.

I quickly scanned that day’s newspapers when I got a chance at a store, and didn’t see anything reported on the front page of the New York Times, among other papers. (I stopped being a regular newspaper reader a few years ago. I do visit some papers’ web sites.) So I didn’t think too much about it.

On Wednesday I checked the web, and understood what happened in Wenchuan, Sichuan Province, China. Just totally shocked, saddened, and cried quite a bit. At the same time, I am really heartened by the overwhelming response from all across China.

One of my favorite rock songs is John Lennon’s rendition of Stand By Me. I translated it as Stand By You in Chinese as the title of this post, in a reverse sort of way. I just want to list it here to show my solidarity to people who are affected and all the rescue workers.

When the night has come
And the land is dark
And the moon is the only light we see
No I won’t be afraid
No I won’t be afraid
Just as long as you stand, stand by me

And darling, darling stand by me
Oh, now, now, stand by me
Stand by me, stand by me

If the sky that we look upon
Should tumble and fall
And the mountain should crumble to the sea
I won’t cry, I won’t cry
No I won’t shed a tear
Just as long as you stand, stand by me

And darling, darling stand by me
Oh, stand by me
Stand by me, stand by me, stand by me

Whenever you’re in trouble won’t you stand by me
Oh, now, now, stand by me
Oh, stand by me, stand by me, stand by me

Darling, darling stand by me
Stand by me
Oh stand by me, stand by me, stand by me

Comments (4)