Proper escape strategy for strings - linux

I'm writing a simple BASH script to generate an LDIF file, which I can then use to add a user to my OpenLDAP server.
This is the script:
#!/bin/bash
#add LDAP user, v1.0, by mbobak, 11/17/2020
if [ $# != 6 ];
then
echo "`basename $0`: error: invalid number of arguments:"
echo "`basename $0` <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>"
exit 1
fi
userid=$1
firstname=$2
lastname=$3
gidnum=$4
uidnum=$5
empno=$6
temppasswd=`slappasswd -s pw4${userid}`
echo ${userid} ${firstname} ${lastname} ${gidnum} ${uidnum} ${empno} ${temppasswd}
sed -e "s/#userid#/${userid}/g" -e "s/#gidnum#/${gidnum}/g" -e "s/#firstname#/${firstname}/g" -e "s/#lastname#/${lastname}/g" -e "s/#uidnum#/${uidnum}/g" -e "s/#empno#/${empno}/g" -e "s/#temppasswd#/${temppasswd}/g" user_tmpl.ldif
I use it with this template:
dn: uid=#userid#,ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: #userid#
gidNumber: #gidnum#
givenName: #firstname#
sn: #lastname#
displayName: #firstname# #lastname#
homeDirectory: /home/#userid#
mail: #userid##nitssolutions.com
loginShell: /bin/bash
cn: #firstname# #lastname#
uidNumber: #uidnum#
employeeType: INT-FT
employeeNumber: #empno#
dn: uid=#userid#,ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: #temppasswd#
This seems to work just fine, except when the output of slappasswd contains a / character.
When that happens, I get the following error:
./add_ldap_user.sh jdoe John Doe 123456 123456 NS1234
jdoe John Doe 123456 123456 NS1234 {SSHA}kTwHVDBiK4ub3laqwaqZpAUwILrW/Vw9
sed: -e expression #7, char 51: unknown option to `s'
Again, this only happens when the output of slappasswd contains a /.
I'm sure I'm missing something simple here, but it's not clear to me what the correct answer is. I can't simply escape the entire expression, or my variable reverts to a static string '${temppasswd}', which doesn't help. I need the value of ${temppasswd} even if it contains characters that need to be escaped.
Help?

this only happens when the output of slappasswd contains a /.
Choose a different s command separating character. Like ~ or any other character.
sed -e "s~#userid#~${userid}~g"
In edge cases with GNU sed you can use any byte, for example you may use C escaping $'\x01' to write 0x01 byte:
sed -e $'s\x01#userid#\x01'"${userid}"$'\x01g'
But I recommend not to reinvent the wheel and use existing templating tools. Change to format of the template from #userid# to just ${userid} and you may use use envsubst.

With envsubst and the following redesigned template:
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${userid}
gidNumber: ${gidnum}
givenName: ${firstname}
sn: ${lastname}
displayName: ${firstname} ${lastname}
homeDirectory: /home/${userid}
mail: ${userid}#nitssolutions.com
loginShell: /bin/bash
cn: ${firstname} ${lastname}
uidNumber: ${uidnum}
employeeType: INT-FT
employeeNumber: ${empno}
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ${temppasswd}
Processed with: program1
#!/usr/bin/env bash
Iam="${0##*/}" # Basename of myself
if [ $# -ne 6 ];
cat <<ERR >&2
$Iam: error: invalid number of arguments:
Usage:
$Iam <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>
ERR
exit 1
fi
userid="$1" firstname="$2" lastname="$3" \
gidnum="$4" uidnum="$5" empno="$6" \
temppasswd=$(slappasswd -s "pw4$userid") \
envsubst <user_tmpl.ldif
Test run with dummy values:
./program1 foo bar baz 666 42 99
foo bar baz 666 42 99 ciWatEpIcs
Output
dn: uid=foo,ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: foo
gidNumber: 666
givenName: bar
sn: baz
displayName: bar baz
homeDirectory: /home/foo
mail: foo#nitssolutions.com
loginShell: /bin/bash
cn: bar baz
uidNumber: 42
employeeType: INT-FT
employeeNumber: 99
dn: uid=foo,ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ciWatEpIcs
And now with a simple here document, it does not even need envsubst
program2:
#!/usr/bin/env bash
Iam="${0##*/}" # Basename of myself
if [ $# -ne 6 ];
then
cat <<ERR >&2
$Iam: error: invalid number of arguments:
Usage:
$Iam <userid> <firstname> <lastname> <gidnum> <uidnum> <empno>
ERR
exit 1
fi
userid=$1
firstname=$2
lastname=$3
gidnum=$4
uidnum=$5
empno=$6
temppasswd=$(slappasswd -s "pw4$userid")
cat <<LDIFTEMPLATE
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ${userid}
gidNumber: ${gidnum}
givenName: ${firstname}
sn: ${lastname}
displayName: ${firstname} ${lastname}
homeDirectory: /home/${userid}
mail: ${userid}#nitssolutions.com
loginShell: /bin/bash
cn: ${firstname} ${lastname}
uidNumber: ${uidnum}
employeeType: INT-FT
employeeNumber: ${empno}
dn: uid=${userid},ou=people,dc=nitssolutions,dc=com
changetype: modify
add: userPassword
userPassword: ${temppasswd}
LDIFTEMPLATE

Related

Check duplicate disk LABEL before mounting it to the system in bash script

is there a way to check if there is duplicate disk LABEL before mounting it to the system?
i need to make sure that if the user have two external drives, if the two of them have the same label, prompt to the user a warning and asking it to remove the duplicated disk.
my code is in the early stages:
if mountpoint -q "${JOB_MOUNT_DIR}"; then
echo " ${JOB_MOUNT_HD_LABEL} já está montado e está pronto para uso"
else
echo "O dispositivo ""${JOB_MOUNT_HD_LABEL}"" não está montado no diretório ""${JOB_MOUNT_DIR}"""
echo "Deseja montar o diretório?"
echo -n "Qual sua opção? [s/n]: "
read -r "opcao"
if [ "$opcao" == "s" ]; then
mkdir -p "${JOB_MOUNT_DIR}/${JOB_MOUNT_HD_LABEL}"
mount -L "${JOB_MOUNT_HD_LABEL}" "${JOB_MOUNT_DIR}/${JOB_MOUNT_HD_LABEL}"
exit 0
else
echo "Disco não irá ser montado"
exit 0
fi
fi
exit 0
some parts are in pt-br i think that will not be a problem
first it checks if that the disk is already mounted, if not it asks to mount, then there is the problem to know which of the two disk with the same LABEL is to mount
You can use:
lsblk -o name,label
NAME LABEL
mmcblk0
└─mmcblk0p1 eMMC
Or you can use:
blkid
/dev/nvme0n1p1: UUID="36D7-B890" TYPE="vfat" PARTUUID="8614534f-01"
/dev/nvme0n1p5: UUID="65885781-bd9b-4c62-afb0-4a82a0e5759e" TYPE="ext4" PARTUUID="8614534f-05"
/dev/mmcblk0p1: LABEL="eMMC" UUID="79ff33b4-2add-4f2f-844e-d7d242c18578" TYPE="ext4" PARTUUID="d4b36674-ab5f-4f15-bb83-313cce242fe4"
You may need to prefix above commands with sudo
If the above commands get your labels correctly, you can pipe the output roughly as follows to list duplicates:
lsblk -o label | sort | uniq -d

changing file creation date by subtracting 4:00 hours

I have a file in c:/users/text.txt
This text.txt have a file creation date, how to get that text.txt creation date and subtract -4:00 using shell script
last_update=$(stat -c "%n %y" $file)
this statement is giving me the file creation date. How can i subtract -4:00 from it?
for suppose lets say text.txt file was created at 04/04/2019 4:00, i want to change that to 04/04/2019 12:00.
%y is not creation but last modification date.
Get the date as seconds since Epoch and subtract 4 hours from it, convert it to human readable form using date, change access and modification times of a file using touch:
$ stat file
File: file
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: b31ch/45852d Inode: 65386 Links: 1
Access: (0600/-rw-------) Uid: (10138/ u0_a138) Gid: (10138/ u0_a138)
Access: 2019-04-04 12:34:56.172954982 +0300
Modify: 2019-04-04 12:34:56.172954982 +0300
Change: 2019-04-04 12:34:56.172954982 +0300
Birth: -
$
$ stat -c '%y' file
2019-04-04 12:34:56.172954982 +0300
$ stat -c '%Y' file
1554370496
$ date -d #$(( $(stat -c '%Y' file) - 4*60*60 ))
Thu Apr 4 08:34:56 +03 2019
$ touch -d "$( date -d #$(( $(stat -c '%Y' file) - 4*60*60 )) )" file
$
$ stat file
File: file
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: b31ch/45852d Inode: 65386 Links: 1
Access: (0600/-rw-------) Uid: (10138/ u0_a138) Gid: (10138/ u0_a138)
Access: 2019-04-04 08:34:56.000000000 +0300
Modify: 2019-04-04 08:34:56.000000000 +0300
Change: 2019-04-04 12:37:14.492954929 +0300
Birth: -
See stat(1), date(1), and touch(1) for further information.

How to forcefully copy a file from Hdfs to linux file system?

For the command, -copyFromLocal there is an option with -f which will forcefully copy the data from Local file system to Hdfs. Similarly with -copyToLocal option I tried with -f option but, it didn't work. So, can anyone please guide me on that.
Thanks,
Karthik
There is not such -f for copytolocal
$ hadoop fs -help
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] <path> ...]
[-cp [-f] [-p | -p[topax]] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]
[-expunge]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] {-n name | -d} [-e en] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setfattr {-n name [-v value] | -x name} <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
Pls refer this for more info Hadoop hdfs commands

How to get root dn in ldap (Ubuntu)

I want to know the root dn in ldap, any command?
Here is what I found in /etc/ldap/slapd.d/cn\=config.ldif
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1
structuralObjectClass: olcGlobal
entryUUID: 6a0e29d2-7341-1036-810b-5902d64537f7
creatorsName: cn=config
createTimestamp: 20170120094900Z
entryCSN: 20170120094900.675648Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20170120094900Z
dose that mean the root dn is 'cn=config'?
Many servers expose such parameters as attributes.
You are looking for the namingContexts attribute.(Some servers also have a defaultNamingContext and/or configContext.)
You must use "base" as the search scope
These are operational attributes, which have to be explicitly requested by name or by the + wildcard
ldapsearch -LLL -h <ldaphost> -b "" -s base +
OR if server ask for credentials
ldapsearch -LLL -h <ldaphost> -s base -D "bindDN" -w "bindPassword" -b "" +
Output
dn:
structuralObjectClass: OpenLDAProotDSE
configContext: cn=config
namingContexts: dc=mydomain
namingContexts: dc=mydomain2,dc=myorg
supportedControl: 2.16.840.1.113730.3.4.9
supportedControl: 1.2.840.113556.1.4.473
supportedControl: 1.3.6.1.4.1.4203.1.9.1.1
.
.
.
supportedExtension: 1.3.6.1.4.1.1466.20037
supportedExtension: 1.3.6.1.4.1.4203.1.11.1
.
.
supportedFeatures: 1.3.6.1.1.14
supportedFeatures: 1.3.6.1.4.1.4203.1.5.1
.
.
supportedLDAPVersion: 3
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: PLAIN
entryDN:
subschemaSubentry: cn=Subschema

How to get ubi volume name by volume ID on linux terminal?

We have 4 volumes on ubi0 and I want to rename the volume name during runtime(dynamically).
I found one option is like getting ubinfo for corresponding volume and parsing result to get the volume name.
example:
ubi0
ubi0_0:
Name: name1
ubi0_1:
Name: name_2
...........
like this till ubi0_4.
say if I want to get the volume 2 name then
ubinfo -d 0 -n 2 |grep "Name:" | sed -e 's|Name:||' -e 's/^ *//'
name_2
command details: -d <UBI device number> -----> ubi0(0)
-n <volume ID> -------> 2
ouptut of ubinfo -d 0 -n 2
Volume ID: 2 (on ubi0)
Type: dynamic
Alignment: 1
Size: mm LEBs (xxxxx bytes, d MiB)
State: OK
Name: name_2
Character device major/minor: zzz:n
reaming is to get the Name string value.
Is there any other easier option to get the volume name by volume id?
volid=2
cat /sys/class/ubi/ubi0_$volid/name

Resources