Technical Article

Script out all linked/remote servers

,

T-SQL which scripts out all linked and remote servers.  Works on SQL 7.0 and 2000.  Remote login password is only decrypted on SQL 7.0.

--Script to script out all linked/remote servers
--Works on 7.0 and 2000 servers
--remote password decrypt only works on 7.0

declare
    @status	    smallint,	     -- server status
    @server         sysname,         -- server name
    @srvid	    smallint,	     -- server id
    @srvproduct     nvarchar(128),   -- product name (dflt to ss)
    @allsetopt      int,	     --sum of all settable options
    @provider       nvarchar(128),   -- oledb provider name
    @datasrc        nvarchar(4000),  -- oledb datasource property
    @location       nvarchar(4000),  -- oledb location property
    @provstr        nvarchar(4000),  -- oledb provider-string property
    @catalog        sysname,         -- oledb catalog property
    @netname	    varchar(30),     -- Server net name
    @srvoption	    varchar(30),     -- server options
    @loclogin       varchar(30),     -- Local user
    @rmtlogin       varchar(30),     -- Remote user
    @selfstatus     smallint,	     -- linked server login status
    @rmtpass        varbinary(256),  -- linked server login password
    @pwdtext        nvarchar(128),   -- linked server decrypted password
    @i              int,             -- linked server pswd decrypt var
    @lsb            tinyint,         -- linked server pswd decrypt var
    @msb            tinyint,         -- linked server pswd decrypt var
    @tmp            varbinary(256)   -- linked server pswd decrypt var

select @allsetopt=number from master.dbo.spt_values
		where type = 'A' and name = 'ALL SETTABLE OPTIONS'  -- Only 7.0 else use 4063
    
declare d cursor for SELECT srvid,srvstatus, srvname, srvproduct, providername, datasource,
	location, providerstring, catalog, srvnetname 
	from master..sysservers
	where srvid > 0  -- Local Server
open d   
   fetch next from d into @srvid, @status, @server, @srvproduct, @provider, @datasrc,
	@location, @provstr, @catalog, @netname
SET NOCOUNT  ON	
	
while (@@FETCH_STATUS<>-1) begin
   
PRINT '--------------------------------'
Print '--      ' + @server
PRINT '--------------------------------'   
If @status in (64,65)               --Remote Server
Begin
	Print 'sp_addserver'
	Print '  @server = '''+ @server + ''''
	Print '  GO'
		
	If @status = 64
	Begin
		Print 'sp_serveroption'
		Print '  @server = '''+ @server + ''','
		Print '  @optname = ''rpc'','
		Print '  @optvalue = ''false'''
		Print '  GO'
	End
	exec ('declare  r cursor for
	select l.name, r.remoteusername from 
	sysremotelogins r join sysservers s on
	r.remoteserverid = s.srvid
	join syslogins l on
	r.sid = l.sid
	where s.srvname = '''+ @server + '''')
	open r
		fetch next from r into @loclogin, @rmtlogin
	while (@@FETCH_STATUS<>-1)
	begin
	Print 'sp_addremotelogin'
	Print '  @remoteserver = '''+ @server + ''','
	Print '  @loginame  = '''+ @loclogin + ''','
	Print '  @remotename = '''+ @rmtlogin + ''''
	Print '  GO'
		fetch next from r into @loclogin, @rmtlogin
	end
	close r
	deallocate r
	
	
End
Else   --Linked server
Begin
	If exists (select * from tempdb..sysobjects where name like '#tmpsrvoption%')
	Begin
	drop table #tmpsrvoption
	End

	Create Table #tmpsrvoption
	(
	srvoption  varchar(30)
	)
	insert #tmpsrvoption
	select v.name
		from master.dbo.spt_values v, master.dbo.sysservers s
		where srvid = @srvid
			and (v.number & s.srvstatus)=v.number
			and (v.number & isnull(@allsetopt,4063)) <> 0 
			and v.number not in (-1, isnull(@allsetopt,4063))
			and v.type = 'A'

	PRINT 'sp_addlinkedserver'
	Print '  @server = '''+ @server + ''''
	Print ',  @srvproduct = ''' + @srvproduct + ''''
	If @srvproduct <> 'SQL Server'   --Cannot specify additional info for SQL Server Product
	Begin
		Print ',  @provider = ''' + @provider + ''''
		Print ',  @datasrc = ''' + @datasrc + ''''
		Print ',  @location = ''' + @location + ''''
		Print ',  @provstr = ''' + @provstr + '''' 
		Print ',  @catalog = ''' + @catalog + ''''
	End
		Print '  GO'
			   
	-- Set all servers options to false, then reset correct server options
	Print 'sp_serveroption'
		Print '  @server = '''+ @server + ''','
		Print '  @optname = ''rpc'','
		Print '  @optvalue = ''false'''
		Print '  GO'
	Print 'sp_serveroption'
		Print '  @server = '''+ @server + ''','
		Print '  @optname = ''rpc out'','
		Print '  @optvalue = ''false'''
		Print '  GO'
	Print 'sp_serveroption'
		Print '  @server = '''+ @server + ''','
		Print '  @optname = ''data access'','
		Print '  @optvalue = ''false'''
		Print '  GO'
		
	declare s cursor for SELECT srvoption
	from #tmpsrvoption
	
	open s  
   	fetch next from s into @srvoption
	
	while (@@FETCH_STATUS<>-1)
	begin
		Print 'sp_serveroption'
		Print '  @server = '''+ @server + ''','
		Print '  @optname = '''+ @srvoption + ''','
		Print '  @optvalue = ''true'''
		Print '  GO'

		fetch next from s into @srvoption
	End
	close s
	deallocate s
	

--Script linked server logins
If exists (select * from tempdb..sysobjects where name like '#tmplink%')
	Begin
	drop table #tmplink
	End

create table #tmplink
(
rmtserver sysname,
loclogin sysname null,
selfstatus smallint,
rmtlogin sysname null
)

insert #tmplink
exec ('sp_helplinkedsrvlogin '''+ @server + '''')

declare ll cursor for
select loclogin, selfstatus, rmtlogin from #tmplink order by rmtlogin

open ll
fetch next from ll into @loclogin, @selfstatus, @rmtlogin

while (@@FETCH_STATUS<>-1)
begin
    -- Use self no remote user/password
If (@selfstatus = 1 and @loclogin is null)
Begin
	Print 'sp_addlinkedsrvlogin'
	Print '  @rmtsrvname = '''+ @server + ''','
	Print '  @useself = ''true'''
	Print '  GO'
End
Else
If (@selfstatus = 1 and @loclogin is not null) Begin
Print 'sp_addlinkedsrvlogin'
	Print '  @rmtsrvname = '''+ @server + ''','
	Print '  @useself = ''true'','
	Print '  @locallogin = '''+ @loclogin + ''','
	Print '  @rmtuser = NULL,'
	Print '  @rmtpassword = NULL'
	Print '  GO'
End
Else
If (@selfstatus = 0 and @rmtlogin is null) Begin
Print 'sp_addlinkedsrvlogin'
	Print '  @rmtsrvname = '''+ @server + ''','
	Print '  @useself = ''false'','
	Print '  @locallogin = NULL,'
	Print '  @rmtuser = NULL,'
	Print '  @rmtpassword = NULL'
	Print '  GO'
End
Else
If (@selfstatus = 0) Begin  -- Check for Use self mappings
	exec ('declare pwd cursor for
	select l.password from master..sysservers s
	join master..sysxlogins l on s.srvid = l.srvid --where l.sid is not null
	where s.srvname = '''+ @server + ''' and l.name = '''+ @rmtlogin + '''')
-- Decrypt passwords
-- Only works for 7.0 server
-- Encrypt algorithm changed in 2000
	open pwd
	fetch next from pwd into @rmtpass
	while @@fetch_status = 0
    	begin
    	set @i = 0
    	set @pwdtext = N''
    	while @i < datalength(@rmtpass)
        begin
        set @tmp = encrypt(@pwdtext + nchar(0))
        set @lsb = convert(tinyint, substring(@tmp, @i + 1, 1))
            ^ convert(tinyint, substring(@rmtpass, @i + 1, 1))
        set @i = @i + 1

        set @tmp = encrypt(@pwdtext + nchar(@lsb))
        set @msb = convert(tinyint, substring(@tmp, @i + 1, 1))
            ^ convert(tinyint, substring(@rmtpass, @i + 1, 1))
        set @i = @i + 1

        set @pwdtext = @pwdtext + nchar(convert(smallint, @lsb)
            + 256 * convert(smallint, @msb))
        end

    	Print 'sp_addlinkedsrvlogin'
	Print '  @rmtsrvname = '''+ @server + ''','
	Print '  @useself = ''false'','
	If (@loclogin is null)
	Begin
		Print '  @locallogin = NULL,'
	End
	Else
		Begin
			Print '  @locallogin = '''+ @loclogin + ''','
		End
	If (@rmtlogin is null)
	Begin
		Print '  @rmtuser = NULL,'
	End
	Else
		Begin
			Print '  @rmtuser = '''+ @rmtlogin + ''','
		End
	If (@pwdtext is null)
	Begin
		Print '  @rmtpassword = NULL'
	End
	Else
		Begin
			print '  @rmtpassword = '''+ @pwdtext + ''''
		End
	Print '  GO'

    	fetch next from pwd into @rmtpass
    end
    close pwd	
    deallocate pwd
End
	fetch next from ll into @loclogin, @selfstatus, @rmtlogin

End
close ll	
deallocate ll
	
	
	
End
If @netname <> @server   -- If the srvnetname.sysservers is different from srvname.sysservers
	Begin
		Print 'sp_setnetname'
		Print '  @server = '''+ @server + ''','
		Print '  @network_name = '''+ @netname + ''''
	End

fetch next from d into @srvid,@status, @server, @srvproduct, @provider, @datasrc,
	@location, @provstr, @catalog, @netname
	
End
close d
deallocate d

Rate

5 (8)

You rated this post out of 5. Change rating

Share

Share

Rate

5 (8)

You rated this post out of 5. Change rating