Find and replace a text in a XML file between two placeholders with a placeholder having special characters - sed

I have a requirement mentioned below.
Sample file.txt ::
<?xml version='1.0' encoding='utf-8'?>
<Server port="${shutdown.port}" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="com.springsource.tcserver.serviceability.rmi.JmxSocketListener"
port="${jmx.port}"
bind="127.0.0.1"
useSSL="false"
passwordFile="${catalina.base}/conf/jmxremote.password"
accessFile="${catalina.base}/conf/jmxremote.access"
authenticate="true"/>
<Listener className="com.springsource.tcserver.serviceability.deploy.TcContainerDeployer" />
<GlobalNamingResources>
<Resource
name="jdbc/myDBPool1"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:#localhost:<dbanme>"
user="myusername"
password="somepassword1"
validationQuery="SELECT 1 FROM DUAL"
/>
<Resource
name="jdbc/myDBPool2"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:#localhost:<dbanme>"
user="myusername"
password="somepassword2"
validationQuery="SELECT 1 FROM DUAL"
/>
<Resource
name="jdbc/myDBPool3"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:#localhost:<dbanme>"
user="myusername"
password="somepassword3"
validationQuery="SELECT 1 FROM DUAL"
/>
</GlobalNamingResources>
<Service name="Catalina">
<Executor name="tomcatThreadPool" namePrefix="tomcat-http--" maxThreads="300" minSpareThreads="50"/>
<Connector executor="tomcatThreadPool"
port="${http.port}"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="${https.port}"
acceptCount="100"
maxKeepAliveRequests="15"/>
<Engine name="Catalina" defaultHost="localhost">
<!--
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true" deployOnStartup="true" deployXML="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
</Server>
I am trying this script to find some text( .password. ) between two strings (inclusive of strings) and then replace it with a placeholder. Whenever my cmdlinepasswd placeholder has special characters say "/" character it fails.
sed -ie "/$datasource/,/password*/ {s/.*password.*/\tpassword=\"$cmdlinepasswd\"/;}" file.txt
assuming
datasource=jdbc/myDBPool1
cmdlinepasswd=new/passwd
I am new to scripting and any help would be appreciated.
Thank you.

This should do it:
awk -v RS= -v ORS='\n\n' -v datasource="jdbc/myDBPool1" -v cmdlinepasswd="new/passwd" '
$0 ~ "^[[:space:]]*<Resource.*name=\"" datasource "\"" {
sub(/password="[^"]+"/,"password=\"" cmdlinepasswd "\"")
} 1' file
It just looks for records that start with <Resource followed by name="<your datasource variable value>" and if it finds one it replaces the password in that record.
If you have shell variables already
datasource="jdbc/myDBPool1"
cmdlinepasswd="new/passwd"
just pass them into awk as:
awk -v RS= -v ORS='\n\n' -v datasource="$datasource" -v cmdlinepasswd="$cmdlinepasswd" '
$0 ~ "^[[:space:]]*<Resource.*name=\"" datasource "\"" {
sub(/password="[^"]+"/,"password=\"" cmdlinepasswd "\"")
} 1' file

One way using perl. It accepts three arguments, the variables to check/substitute and the input file. It's better than sed because it does quotemeta (\Q) to arguments, that escapes many special characters of a regex.
perl -pe '
## Get arguments but input file.
BEGIN { ($datasource,$cmdlinepasswd) = (shift,shift) }
## Get a range from resource name until the line with the password.
if ( $range = ( m/=\s*"\Q${datasource}"/ ... /password\s*=/ ) ) {
## "E0" points to last line (that contains the password, so
## change it.
if ( q|E0| eq substr $range, -2 ) {
s/(=\s*").*("\s*)$/$1${cmdlinepasswd}$2/;
}
}
' "$datasource" "$cmdlinepasswd" infile
With your example input data, it yields (only showed the part of the password that was modified, and left the rest untouched):
<?xml version='1.0' encoding='utf-8'?>
<Server port="${shutdown.port}" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="com.springsource.tcserver.serviceability.rmi.JmxSocketListener"
port="${jmx.port}"
bind="127.0.0.1"
useSSL="false"
passwordFile="${catalina.base}/conf/jmxremote.password"
accessFile="${catalina.base}/conf/jmxremote.access"
authenticate="true"/>
<Listener className="com.springsource.tcserver.serviceability.deploy.TcContainerDeployer" />
<GlobalNamingResources>
<Resource
name="jdbc/myDBPool1"
auth="Container"
type="oracle.jdbc.pool.OracleDataSource"
description="Oracle Datasource"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
url="jdbc:oracle:thin:#localhost:<dbanme>"
user="myusername"
password="new/passwd"
validationQuery="SELECT 1 FROM DUAL"
/>
...
NOTE: After see your edit, it would be a better option to use an xml parser, but this solution seems to work in my test.

Related

PowerShell script returning node count of 0

I am trying to use PowerShell to count the number of operation nodes in my XML file.
[xml]$doc = [xml]#'
<?xml version="1.0" encoding="utf-8"?>
<DeploymentReport xmlns="http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02"><Alerts />
<Operations>
<Operation Name="Alter">
<Item />
<Item />
<Item />
</Operation>
</Operations>
</DeploymentReport>
'#
$info = $doc.SelectNodes("/DeploymentReport/Operations/Operation")
$info.count
However, $info.count is always returning 0. What am I doing wrong?
You're not selecting the nodes with the correct namespace. You'd need to do something like:
[Xml] $Doc = [Xml]#'
<?xml version="1.0" encoding="utf-8"?>
<DeploymentReport xmlns="http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02">
<Alerts/>
<Operations>
<Operation Name="Alter">
<Item/>
<Item/>
<Item/>
</Operation>
</Operations>
</DeploymentReport>
'#
$NSM = New-Object System.Xml.XmlNamespaceManager $Doc.NameTable
$NSM.AddNamespace("dr", "http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02")
$Info = $Doc.SelectNodes("/dr:DeploymentReport/dr:Operations/dr:Operation", $NSM)
$Info.Count
1

How to work with PowerShell to change values of Web.Config file?

I am working on PowerShell. In that am trying to change the values of an existing config file values with the help of PowerShell and its working well.
But I faced a new task as below and strucked here in converting the values in PowerShell to override in my config file. For this task, I referred this link
If had a Code like this :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="service.tasks" type="HRNetTaskService.TaskConfigurationSection, TaskService" />
</configSections>
<connectionStrings>
<add name="Production" connectionString="" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="RestServiceUrl" value="XXXXXXXXXXX" />
</appSettings>
<service.tasks>
<tasks>
<!-- App.config specified tasks are always recurring starting from whenever The Service first schedules it -->
<task name="ExpireRequirements" taskName="ExpireRequirements" recurrenceFactor="1" recurrenceType="Days" executeTime="01:00">
<parameters>
<param key="entityID">00000000-0000-0000-0000-000000000E01</param>
</parameters>
</task>
<task name="RequestExpiredRequirementsTask" taskName="RequestExpiredRequirementsTask" recurrenceFactor="1" recurrenceType="Days" executeTime="01:00">
<parameters>
<param key="entityID">00000000-0000-0000-0000-000000000E01</param>
<param key="CopyBatchSize">50</param>
</parameters>
</task>
<task name="UpdateRequirementChecksEffectiveDateTask" taskName="UpdateRequirementChecksEffectiveDateTask" recurrenceFactor="1" recurrenceType="Days" executeTime="01:00">
<parameters>
<param key="entityID">00000000-0000-0000-0000-000000000E01</param>
</parameters>
</task>
<task name="PeoplenetMatchAssignmentRefresh" taskName="PeoplenetMatchAssignmentRefresh">
<parameters>
<param key="checkInterval">300000</param>
<param key="batchCount">100</param>
</parameters>
</task>
</tasks>
</service.tasks>
<system.net>
<connectionManagement>
<add address="*" maxconnection="48" />
</connectionManagement>
</system.net>
<system.runtime.remoting>
<application name="server">
<channels>
<channel ref="tcp" port="8090">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full" />
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
How to change the values inside the service.tasks tag and system.runtime.remoting tags.
Refer to this code to update entityID value in ExpireRequirements task element (specify config file path in argument:-webCofig xxx):
param(
[string]$webConfig
)
$doc = (Get-Content $webConfig) -as [Xml]
$root=$doc.get_DocumentElement()
$ExpireRequirementsTask=$root."service.tasks"."tasks"."task" | where {$_.name -eq 'ExpireRequirements'}
Write-Output $ExpireRequirementsTask
$ExpireRequirementsTaskEntityID=$ExpireRequirementsTask."parameters"."param" | where {$_.key -eq 'entityID'}
Write-Output $ExpireRequirementsTaskEntityID
$ExpireRequirementsTaskEntityID.InnerText="11111111-0000-0000-0000-000000000E01"
$doc.Save($webConfig)

Start OrientDB studio for plocal DB

I'm able to start my orientDb (2.2.6) instance using a plocal connection and able to add vertices to the DB but I can't access the studio. When I go to http://localhost:2480, the page is blank. Isn't studio ready and available 'out of the box'?
orientdb-server-config.xml is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<orient-server>
<network>
<protocols>
<protocol implementation="com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary" name="binary"/>
<protocol name="http" implementation="com.orientechnologies.orient.server.network.protocol.http.ONetworkProtocolHttpDb"/>
</protocols>
<listeners>
<listener protocol="binary" socket="default" port-range="2424-2430" ip-address="0.0.0.0"/>
<listener protocol="http" port-range="2480-2485" ip-address="0.0.0.0">
<commands>
<command implementation="com.orientechnologies.orient.server.network.protocol.http.command.get.OServerCommandGetStaticContent" pattern="GET|www GET|studio/ GET| GET|*.htm GET|*.html GET|*.xml GET|*.jpeg GET|*.jpg GET|*.png GET|*.gif GET|*.js GET|*.css GET|*.swf GET|*.ico GET|*.txt GET|*.otf GET|*.pjs GET|*.svg">
<parameters>
<entry value="Cache-Control: no-cache, no-store, max-age=0, must-revalidate\r\nPragma: no-cache" name="http.cache:*.htm *.html"/>
<entry value="Cache-Control: max-age=120" name="http.cache:default"/>
</parameters>
</command>
</commands>
</listener>
</listeners>
</network>
<users>
<user resources="*" password="root" name="root"/>
<user resources="connect,server.listDatabases,server.dblist" password="guest" name="guest"/>
</users>
<properties>
<entry value="1" name="db.pool.min"/>
<entry value="50" name="db.pool.max"/>
<entry value="true" name="profiler.enabled"/>
</properties>
</orient-server>
I get these warnings whenever I try to access localhost:2480 from Chrome:
2016-09-28 16:56:01:756 WARNI path variable points to 'src/site' but it doesn't exists [OServerCommandGetStaticContent]
2016-09-28 16:56:01:756 WARNI path variable points to 'src/site' but it isn't a directory [OServerCommandGetStaticContent]
What am I missing?

How can I add Windows Networking events to my custom wprp file?

I'm trying to capture an etl trace on the HoloLens with my own events, and some generic networking events. Using WPR on my PC, I can choose Networking I/O activity, which will show events like Microsoft-Windows-TCPIP when I analyze in WPA. I can't figure out how to see these events on a HoloLens, or successfully put them in my wprp file.
I've tried the following with no success, even on Windows. My own events work fine.
<EventProvider Id="Microsoft.Windows.TCPIP" Name="2F07E2EE-15DB-40F1-90EF-9D7BA282188A"/>
...
<EventProviderId Value="Microsoft.Windows.TCPIP"/>
Here is an WPRP file that captures "Microsoft-Windows-TCPIP" and "Microsoft-Windows-Kernel-Network" events.
<?xml version="1.0" encoding="utf-8"?>
<WindowsPerformanceRecorder Version="1.0" Author="MagicAndre1981" Copyright="MagicAndre1981" Company="MagicAndre1981">
<Profiles>
<SystemCollector Id="SystemCollector" Name="NT Kernel Logger">
<BufferSize Value="1024" />
<Buffers Value="512" />
</SystemCollector>
<EventCollector Id="EventCollector_UserModeEvents_Session" Name="UserModeEvents_Session">
<BufferSize Value="1024" />
<Buffers Value="512" />
</EventCollector>
<SystemProvider Id="SystemProvider">
<Keywords>
<Keyword Value="ProcessThread" />
<Keyword Value="Loader" />
<Keyword Value="SampledProfile" />
<Keyword Value="Interrupt"/>
<Keyword Value="DPC"/>
<Keyword Value="ReadyThread" />
<Keyword Value="CSwitch" />
<Keyword Value="NetworkTrace" />
</Keywords>
<Stacks>
<Stack Value="SampledProfile" />
<Stack Value="CSwitch" />
<Stack Value="ReadyThread" />
<Stack Value="ImageLoad" />
<Stack Value="ImageUnload" />
</Stacks>
</SystemProvider>
<EventProvider Id="NetworkingCorrelation" Name="Microsoft-Windows-Networking-Correlation" Level="5" Stack="true">
<Keywords>
<Keyword Value="0x7FFF0000000F"/>
</Keywords>
</EventProvider>
<EventProvider Id="KernelNetwork" Name="Microsoft-Windows-Kernel-Network" Level="5" Stack="true" NonPagedMemory="true"/>
<EventProvider Id="TCP" Name="Microsoft-Windows-TCPIP" Level="5" Stack="true" NonPagedMemory="true">
<Keywords>
<Keyword Value="0x0000000400000000"/>
</Keywords>
</EventProvider>
<Profile Id="NetworkProfile.Verbose.File" Name="NetworkProfile" Description="Network Profile" LoggingMode="File" DetailLevel="Verbose">
<Collectors>
<SystemCollectorId Value="SystemCollector">
<SystemProviderId Value="SystemProvider" />
</SystemCollectorId>
<EventCollectorId Value="EventCollector_UserModeEvents_Session">
<EventProviders>
<EventProviderId Value="NetworkingCorrelation" />
<EventProviderId Value="KernelNetwork" />
<EventProviderId Value="TCP" />
</EventProviders>
</EventCollectorId>
</Collectors>
</Profile>
<Profile Id="NetworkProfile.Verbose.Memory" Name="NetworkProfile" Description="Network Profile" Base="NetworkProfile.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
</Profiles>
<TraceMergeProperties>
<TraceMergeProperty Id="BaseVerboseTraceMergeProperties" Name="BaseTraceMergeProperties" Base="">
<FileCompression Value="true" />
<CustomEvents>
<CustomEvent Value="ImageId"/>
<CustomEvent Value="BuildInfo"/>
<CustomEvent Value="VolumeMapping"/>
<CustomEvent Value="EventMetadata"/>
<CustomEvent Value="PerfTrackMetadata"/>
<CustomEvent Value="NetworkInterface"/>
</CustomEvents>
</TraceMergeProperty>
</TraceMergeProperties>
</WindowsPerformanceRecorder>
Run it via "C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\wpr.exe" -start network.wprp and next "C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\wpr.exe" -stop NetworkData.etl

add xml attribute "xsi:nil"

I am reading the following file in powershell.
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<nested1>
<level1 xsi:nil="true" />
<level2>2</level2>
</nested1>
<nested2>
<level1 xsi:nil="true" />
<level2>2</level2>
</nested2>
</root>
using...
[xml]$XmlDoc = get-content $XMLFile
I would like to set
$XmlDoc.root.nested1.level2
so it has the attribute xsi:nil="true"
so the file appears as
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<nested1>
<level1 xsi:nil="true" />
<level2 xsi:nil="true" />
</nested1>
<nested2>
<level1 xsi:nil="true" />
<level2>2</level2>
</nested2>
</root>
Many Thanks for any advice offered.
Use SetAttribute() and provide the namespace URI.
$node = $XmlDoc.SelectSingleNode('//nested1/level2')
$node.SetAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance', 'true') |
Out-Null