내 ova에는 두 개의 vmdk 파일이 있습니다. ovf 파일은 두 vmdk 파일의 기능을 포함하는 xml입니다. 파일의 내용은 다음과 같습니다
<ovf:VirtualSystem ovf:id="VMDK1">
<ovf:Item>
<rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
<rasd:Description>Number of Virtual CPUs</rasd:Description>
<rasd:ElementName>8 virtual CPU(s)</rasd:ElementName>
<rasd:InstanceID>6</rasd:InstanceID>
<rasd:Reservation>9000</rasd:Reservation>
<rasd:ResourceType>3</rasd:ResourceType>
<rasd:VirtualQuantity>8</rasd:VirtualQuantity>
<rasd:Weight>8000</rasd:Weight>
<vmw:CoresPerSocket ovf:required="false">8</vmw:CoresPerSocket>
</ovf:Item>
<ovf:Item>
<rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
<rasd:Description>Memory Size</rasd:Description>
<rasd:ElementName>12288 MB of memory</rasd:ElementName>
<rasd:InstanceID>7</rasd:InstanceID>
<rasd:Reservation>12288</rasd:Reservation>
<rasd:ResourceType>4</rasd:ResourceType>
<rasd:VirtualQuantity>12288</rasd:VirtualQuantity>
<rasd:Weight>122880</rasd:Weight>
</ovf:Item>
</ovf:VirtualSystem>
<ovf:VirtualSystem ovf:id="VMDK2">
<ovf:Item>
<rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
<rasd:Description>Number of Virtual CPUs</rasd:Description>
<rasd:ElementName>14 virtual CPU(s)</rasd:ElementName>
<rasd:InstanceID>7</rasd:InstanceID>
<rasd:Reservation>9000</rasd:Reservation>
<rasd:ResourceType>3</rasd:ResourceType>
<rasd:VirtualQuantity>14</rasd:VirtualQuantity>
<rasd:Weight>14000</rasd:Weight>
<vmw:CoresPerSocket ovf:required="false">14</vmw:CoresPerSocket>
</ovf:Item>
<ovf:Item>
<rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
<rasd:Description>Memory Size</rasd:Description>
<rasd:ElementName>15360 MB of memory</rasd:ElementName>
<rasd:InstanceID>8</rasd:InstanceID>
<rasd:Reservation>15360</rasd:Reservation>
<rasd:ResourceType>4</rasd:ResourceType>
<rasd:VirtualQuantity>15360</rasd:VirtualQuantity>
<rasd:Weight>153600</rasd:Weight>
</ovf:Item>
</ovf:VirtualSystem>
sed를 사용하여 VMDK2의 다음 CPU 구성만 변경하고 싶습니다.
<rasd:ElementName>14 virtual CPU(s)</rasd:ElementName>
<rasd:VirtualQuantity>14</rasd:VirtualQuantity>
<vmw:CoresPerSocket ovf:required="false">14</vmw:CoresPerSocket>
VirtualQuantity 요소도 포함하는 VMDK2의 메모리 구성을 수정하고 싶지 않습니다.
아래에서 시도했지만 VMDK1 및 VMDK2 CPU 구성이 모두 수정되었습니다.
sed -i "/hertz/,/CoresPerSocket/s/[0-9]\+ virtual CPU/$cores virtual CPU/
/hertz/,/CoresPerSocket/s%<rasd:VirtualQuantity>[0-9]\+</rasd:VirtualQuantity>%<rasd:VirtualQuantity>$cores</rasd:VirtualQuantity>%
/CoresPerSocket/s/[0-9]\+/${cores}/" $ovf
답변1
XML을 이해하는 XML 파서를 사용하여 이를 올바르게 수행하는 방법은 다음과 같습니다.
ncpus=16
xmlstarlet edit \
-N xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" \
-N xmlns:vcloud="http://www.vmware.com/vcloud/v1.5" \
-N xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" \
-N xmlns:vmw="http://www.vmware.com/schema/ovf" \
--var vi '//ovf:VirtualSystem[@ovf:id="VMDK2"]/ovf:Item[rasd:Description="Number of Virtual CPUs"]' \
--update '$vi/rasd:ElementName' --value "$ncpus virtual CPU(s)" \
--update '$vi/rasd:VirtualQuantity' --value "$ncpus" \
--update '$vi/vmw:CoresPerSocket' --value "$ncpus" \
ova.ovf
<ovf:VirtualSystem id="VMDK2"/>
그러면 청크가 선택 되고 <ovf:Item/>
포함된 하위 섹션이 선택됩니다 <rasd:Description>Number of Virtual CPUs</>
. 그런 다음 $ncpus
CPU 수를 셸 변수 값(예제에서는 16)으로 바꿉니다. 이러한 매개변수는 XML 데이터를 올바르게 구문 분석하는 -N {namespace}
데 필요합니다 . xmlstarlet
(간단한 단일 네임스페이스의 경우 일반적으로 기본 _
이름을 사용할 수 있지만 여기서는 다양한 요소의 네임스페이스를 명시적으로 식별해야 합니다.)
합법적인 XML 파일로 만들기에 충분한 XML을 포함하도록 원래 예제를 수정해야 했습니다.
<Item xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:vcloud="http://www.vmware.com/vcloud/v1.5"
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
xmlns:vmw="http://www.vmware.com/schema/ovf"
>
<ovf:VirtualSystem ovf:id="VMDK1">
…your examples here…
</ovf:VirtualSystem>
</Item>
많은 도구와 마찬가지로 이 명령은 편집된 출력을 다음과 같이 생성합니다.표준 출력. 당신은 그것을 사용할 수 있습니다제자리에정말로 원한다면 표시하십시오. 그러나 테스트할 때는 그렇지 않습니다. 그러나 제가 평소 선호하는 것은 파일을 백업으로 저장하고 편집된 결과를 원래 이름에 쓰는 것입니다. 이 접근 방식은 모든 도구에서 작동하며 원본 버전에 있었을 수 있는 하드 링크, 권한 및 기타 메타데이터를 그대로 유지합니다.
xmlstarlet ... "original_file" >"original_file.$$.tmp" &&
cp -fp "original_file" "backup_file" &&
cat "original_file.$$.tmp" >"original_file"
rm -f "original_file.$$.tmp"
(하드 링크와 메타데이터에 관심이 없다면 이를 단순화하고 cat
로 대체할 수 있습니다 mv -f
.)
답변2
쉘 변수 $cores
에 동적으로 할당된 값(예: )이 있다고 가정하면 cores=$(grep -c processor /proc/cpuinfo)
다음과 같은 것을 사용할 수 있습니다.
awk -v RS='</ovf:VirtualSystem>' \
-v ORS='</ovf:VirtualSystem>' \
-v cores="$cores" \
'/ovf:id="VMDK2"/ {
sub(/<rasd:VirtualQuantity>[0-9]+<\/rasd:VirtualQuantity>/, "<rasd:VirtualQuantity>" cores "</rasd:VirtualQuantity>");
sub(/<rasd:ElementName>[0-9]+ virtual CPU\(s\)<\/rasd:ElementName>/, "<rasd:ElementName>" cores " virtual CPU(s)</rasd:ElementName>");
}
NR > 1 {
print prev_rs
}
{
prev_rs = $0
}
END {
printf("%s", prev_rs)
}' your_xml_file.xml