Reputation: 3871
I'd like to replace one string in file with another, to be more specific, replace username:password entry in dovecot passwd file ( /etc/dovecot/passwd
) but only if record exists.
So, what I need:
sed
commandHere is /etc/dovecot/passd
example:
[email protected]:{CRAM-MD5}479375185777b7ba573747c111483bdd628332a70268ce283dc80bedd0f65988
[email protected]:{CRAM-MD5}10b7176649d8bb3eb38f6b68a0c6c826ffab5656181821e598296ebd31e8f64f
and what I've tried so far (creates new file, output to new and mv
to original even if record does not exist)
#!/usr/bin/env php
<?php
$passwd_file = '/etc/dovecot/passwd';
$time = time();
$newtempfile = '/tmp/' . $time . 'dvctpwd';
/**
* $search generates replace target [email protected]:{CRAM-MD5}479375185777b7ba573747c111483bdd628332a70268ce283dc80bedd0f65988
* if [email protected] gives correct password to dovecot's doveadm pw -u [email protected] -poldpassword
**/
$search = $argv[1] .':' . exec("doveadm pw -u " . $argv[1] . " -p" . $argv[2]);
/**
* $replace generates replace value [email protected]:{CRAM-MD5}...
* i.e. scheme with new password
**/
$replace = $argv[1] .':' . exec("doveadm pw -u " . $argv[1] . " -p" . $argv[3]);
$command = <<<DD
sed -e "s|$search|$replace|" $passwd_file > $newtempfile && mv $newtempfile $passwd_file && echo "Password changed!\n";
DD;
$output = passthru($command);
echo $output . PHP_EOL;
Upvotes: 0
Views: 2631
Reputation: 88563
With GNU sed to edit your file "in place":
a="[email protected]"
md5="abc123"
sed -i 's/^'"$a"'.*/'"$a"':{CRAM-MD5}'"$md5"'/' /etc/dovecot/passd
Output in file /etc/dovecot/passd:
[email protected]:{CRAM-MD5}abc123 [email protected]:{CRAM-MD5}10b7176649d8bb3eb38f6b68a0c6c826ffab5656181821e598296ebd31e8f64f
Upvotes: 1
Reputation: 1499
While you can use sed to make substitutions in place with the -i flag, the last-modified time of the file will always be updated:
sed -i "s|$search|$replace|" "$passwd_file"
Indeed, note that the time of file birth, time of last access, as well as time of last modification will be updated with the command above. This can be shown by doing the following command both before and after the above sed command:
stat -c "%W %X %Y %Z" "$passwd_file"
Also, the above sed command will return 0 whether or not a replacement happens.
So, if you absolutely must not update the file at all, including timestamps, you can do:
grep -q "$search" "$passwd_file" &&
sed -i "s|$search|$replace|" "$passwd_file"
And if you need to show a message that the file has been updated, you can use a list:
grep -q "$search" "$passwd_file" &&
{
sed -i "s|$search|$replace|" "$passwd_file"
echo -e "Password changed!\n"
}
Finally, if you wish to also have a message that is shown if the password is not changed, you can do:
grep -q "$search" "$passwd_file" &&
{
sed -i "s|$search|$replace|" "$passwd_file"
printf "Password changed!\n\n"
} || printf "Password not changed!\n\n"
To do the above as a single line, be sure to add semicolons in the list, including the last element:
grep -q "$search" "$passwd_file" && { sed -i "s|$search|$replace|" "$passwd_file"; printf "Password changed!\n\n"; } || printf "Password not changed!\n\n"
Some notes:
Upvotes: 2