sed permission denied when overwriting file - linux

I am trying to use sed to overwrite my index.php file, but I am getting an error:
$ sed -i 's#<head>#<head><script type="text/javascript" src="new.js"></script>#' index.php
sed: couldn't open temporary file ./sedmZNx8T: Permission denied
Does anyone know how to fix this?

Really no great answers here. Sorry if thread is dead, it came up in google searches and nothing really answered the question. Although altendky's answer is sort of the same as mine... There IS a workaround...find a world writable directory, say /tmp
cp /etc/file_to_mod /tmp
sed -i -e 's/foo/bar/g' /tmp/file_to_mod
cat /tmp/file_to_mod >/etc_file_to_mod
Hope that helps!

While editing a file in place, sed creates a temporary file, saves the result and then finally mv the original file with the temporary one.
The problem is that you don't have write permission in the directory where sed is trying to create the temp file.
As the file is /tmp/file, check the permission of the directory where you are running the command.

Seems like you have a permission issue on the /tmp dir. (as discussed bellow, you run command in phpshell, so TMP dir can be setted elsewhere than /tmp)
It should looks like :
$ ls -ld /tmp
drwxrwxrwx 333 root root 32768 12 oct. 03:13 /tmp/
explanations
When invoking sed with -i flag, sed create a temporary file in /tmp dir.
Proof with strace :
$ strace -f -e trace=file sed -i 's/a/z/' /tmp/a
execve("/bin/sed", ["sed", "-i", "s/a/z/", "/tmp/a"], [/* 94 vars */]) = 0
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
(...)
open("/tmp/sedPSBTPG", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("/tmp/sedPSBTPG", "/tmp/a") = 0
+++ exited with 0 +++

I think you can you "sudo" in front of your command. Like
sudo sed -i 's/geteuid/getppid/g' /usr/bin/vlc
It worked for me.

Given that you do not have write access to the directory where index.php is stored, then generally you would not have access to index.php...? Assuming this is a 'non-standard' case and you do have write access, sed -i is trying to create a temp file in the same directory as index.php (just checked and it is the same directory, not the CWD). Run sed without -i and end the line with something like > ~/sed.out to write the result into a file in your home directory. Then do what you will with that file.
sed 's#<head>#<head><script type="text/javascript" src="new.js"></script>#' index.php > ~/sed.out
Be aware that you while you can cp ~/sed.out index.php you can not mv ~/sed.out index.php. It would seem that cp will put the contents into index.php (not modifying the directory you do not have write permissions to) while mv tries to change the directory (that you don't have write permissions to).

check for the /tmp folder permission
It should have the following permission
drwxrwxrwt 7 root root 4.0K Nov 16 15:06 tmp
If it is not ok for you then run the following commands
sudo chown root:root /tmp
sudo chmod 1777 /tmp
once this is done, then put a sudo infront of your sed command to execute the command as a root user.
This will solve the issue

If the use of sed is not a hard requirement, you can probably use the highly ignored command ed.
ed -s index.php <<< $'%s#<head>#<head><script type="text/javascript" src="new.js"></script>#\nwq'
The <command> <<< '<my_input_string>' construct will pipe '<my_input_string>' into the <command> as standard input
The $'...' construct will be parsed for special characters. In this case the \n splits the string into two lines
You can use any construct you want to generate and pipe in the input (echo, printf, etc.)
Standard Input String:
%s#<head>#<head><script type="text/javascript" src="new.js"></script>#
wq
The first line is your regex search and replace as command for ed. The second line tells ed to write the changes and quit. You may recognize these commands from vi.
source: mrbluecoat.blogspot.com/2014/03/in-place-editing-right-way-hint-dont.html

I think there is a much easier solution. You can just print the file to the standard output and then use the sed on the stream. Afterward, you just redirect the stream to the same file. Obviously, it is a risky solution cause if you are not 100% sure that you know what you are doing you might lose the entire content of the file in question.
cat index.php | sed 's#<head>#<head><script type="text/javascript" src="new.js"></script>#' > index.php

You need to have the write permissions to the folder whose file you are changing.
As explained here: https://stackoverflow.com/a/36404569/5381704

Short answer :
$ chmod +w .
And re-run sed.
Long answer :
As already said, the problem come from the fact that you don't have write permission on . (the current directory from which you run sed). If you are on your own machine/drive then you surely can give yourself the permission to write on this directory, that's what the chmod do here, unless you want protect it for some reason. However, if your on a network drive and can't change your permission on it then you should ask the one that own the directory to do it or use a workaround solution like copy-modify-past the file somewhere else.

I had the same problem under Windows 10. I know, not the OPs question but maybe it helps other people comming from Google.
The solution for me was to remove/move the folder I am working on from the randsomeware protected folders.

Related

Is it possible to change directory mode so that no one can create new files in it?

Say that I have the folder /dir. Is there a command in bash that I can use so that after performing it, no one could create new files in /dir?
Edit: important to mention that after performing the command, there will be same permissions to the directory files as they were before. For example, if I have folder /dir with file a.txt in it - so after I use my desired command I cant create new files, but I can modify/delete a.txt if I want.
you could change the permission with chmod to only let people read the folders content.
chmod a-w /dir
Will remove all write permissions of all (ugo), but keep x (execute) and r (read) permissions intact.
Yes, it's pretty simple. Just chmod to read only. Here is a sample
chmod -R 0444 /path/to/your/dir/
Where the last 3 4's mean User-readonly, Group-readonly and others-readonly respectively.

cpanel shell script on cloud server centos no such file or dir

I have a shell script copy_files.sh which I call once a day using a cron job.
However it has never worked I keep getting no such file or directory.
!#/bin/sh
for f in /home/site1/public_html/admin/data/*.csv
do
cp -v "$f" /home/site2/app/cron_jobs/data/"${f%.csv}".csv
done
I have checked via ssh that all paths are correct I have varified the path to /bin/sh using ls -l /bin/sh I have set perms and user and group to root for copy_files.sh I have disabled php open_basedir protection.
the shell script is in /home/site2/
Any ideas why I am still getting no such file or directory?
Is there anyway to check open_basedir protection is off that said considering the script is owned by root I don't see that being the problem unless it's executed as site2 user and not root?
Because of the way you use shell expansion, the variable in your for loop contains the absolute path to your files. Having the absolute path, means there is no need to use string manipulation (%) nor do you need to add the ".csv" to the filename, just get rid of it all together and provide the directory to which you're copying as your second argument to cp, see the example below.
#!/bin/sh
for f in /home/site1/public_html/admin/data/*.csv; do
cp -v "$f" /home/site2/app/cron_jobs/data
done

Issue in mv command in shell script

Im trying to run mv command using shell script but it gives me
mv: cannot stat `/opt/logs/merchantportal/logger.log.20160501.*': No such file or directory
mv: cannot stat `/opt/logs/merchantapi/logger.log.20160501.*': No such file or directory
// THIS IS MY SHELL SCRIPT
#!/bin/bash
now="$(date +'%Y%m%d')"
merchantPortalLogsPath="/opt/logs/merchantportal"
merchantApiLogsPath="/opt/logs/merchantapi"
currentDate="$(date +%Y%m%d)"
olderDate="$(date "+%Y%m%d" -d "1 days ago")"
merchantPortalLogsPathBackup=$merchantPortalLogsPath"."$olderDate
merchantApiLogsPathBackup=$merchantApiLogsPath"."$olderDate
mkdir $merchantPortalLogsPathBackup
mkdir $merchantApiLogsPathBackup
echo $merchantPortalLogsPath"/logger.log."$olderDate".*" $merchantPortalLogsPathBackup"/"
echo $merchantApiLogsPath"/logger.log."$olderDate".*" $merchantApiLogsPathBackup"/"
mv $merchantPortalLogsPath"/logger.log."$olderDate".*" $merchantPortalLogsPathBackup"/"
mv $merchantApiLogsPath"/logger.log."$olderDate".*" $merchantApiLogsPathBackup"/"
// BUT DIRECTORY IS CREATED SUCCESSFULLY
".*"
Putting the * inside double quotes will prevent the shell from treating that as a wildcard and will instead take it as a literal * character. Instead, change your script so that it does not double quote the *. For example:
mv ${merchantPortalLogsPath}/logger.log.${olderDate}.* ${merchantPortalLogsPathBackup}/
mv ${merchantApiLogsPath}/logger.log.${olderDate}.* ${merchantApiLogsPathBackup}/
Note: Technically should actually double quote the variable expansions to handle paths with spaces and other special characters in them. But I have not shown that to focus just on the problem at hand.
The log directories exist, but the log files within those directories did not. Since mv cannot move from data a log file that doesn't first exist, it complains, rather vaguely:
No such file or directory
Note: IMHO vague error messages are documentation/interface bugs -- if the error had said only:
No such file
And not left the user wondering if there was a missing directory it would have seemed less puzzling, since that message would clearly imply that the directory where the file was supposed to exist did in fact exist.
But consider this egregious GNU mv example, where a directory /tmp/a/ does not exist:
mv /tmp/a/b/c/d /tmp/foo
Output to STDERR:
mv: cannot stat '/tmp/a/b/c/d': No such file or directory
Now, the directory /tmp/a/ doesn't exist, and also the directories /tmp/b/ and /tmp/a/b/c/, and the file /tmp/a/b/c/d, none of them exist. The user is given no indication of which of those is the problem, and it's even possible (unusual, but possible) that /tmp/ doesn't exist. Where as writing just a few lines of code could output an error message that said something so much more useful, like:
mv: cannot stat '/tmp/a/b/c/d': `/tmp/` exists, but not directory `/tmp/a/`
...which collectively would probably save years of user-time.

How to allow any user on the server to edit a specific file?

I have created this code which will allow user to change the port in a specific file,
#Change Port
IRSSIPORT1=`head -n 1 /etc/ports.txt | tail -n 1`
sudo perl -pi -e "s/^$IRSSIPORT1.*\n$//g" /etc/ports.txt
sudo perl -pi -e "s/web_port = 8081/web_port = $IRSSIPORT1/g" .sickbread/config.ini
echo "sickbread Port: $IRSSIPORT1" | sudo tee -a $HOME/private/SBinfo.txt
What this code do is it takes a number from a file and then put it in the config file where it is required to change and deletes that number from the initial file from where it took it, but it requires read access as well as write access,
I tried everything in my knowledge to get it work without sudo, but i failed to do it.
Any suggestion?
I get this error -
Can't remove /etc/ports.txt: Permission denied, skipping file.
You can't do inplace edit on 666 files inside /etc as -i switch makes new file and deletes old one inside directory.
Since users don't have sufficient permissions to add/delete files from /etc (nor it would be good idea to do so), you have to read all file content at once, change it, and write back to the same file. Using a temporary file is also a workable solution.
While it may seem that the question is more about system administration rather than about programming, it's actually somewhat about perl so it's may be a good place for it here.
Doing chmod 666 /etc/ports.txt grants all users read-write access to this particular file (of course you don't need to put 777 as it's not an executable or script). So anyone will be able to open this file for writing and put any contents in it.
But when you do perl -pi -e ... /etc/ports.txt you don't only write into that file. Instead, perl will want to delete and then recreate this file, as shown here in strace output:
# strace perl -pi -e 's/a/b/' /etc/ports.txt 2>&1 | grep /etc/ports.txt
...
open("/etc/ports.txt", O_RDONLY) = 3
unlink("/etc/ports.txt") = 0
open("/etc/ports.txt", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
To delete the file it will need to have a write access not to the file itself, but to the directory /etc, which of course you cannot give to any user.
So I suppose you just don't need to try using in-place edit as it's always related to removing or renaming files, but instead get the contents of the file, make required changes and then write it back to the same file.

Linux command to move a directory

My old and new directory have same folders and files inside.
I try:
mv -if old/* new/*
and get error
mv: cannot move `./xxxxxx' to a subdirectory of itself
How can I move it?
You should use mv -if old/* new/ without the trailing *.
This is because it unrolled to
mv -if old/foo old/bar old/baz new/foo new/bar new/baz
i.e. move everything into new/baz
This is not what you wanted.
reef#localhost:/tmp/experiment$ ls a
11 22 33
reef#localhost:/tmp/experiment$ ls b
22 33
reef#localhost:/tmp/experiment$ ls
a b
reef#localhost:/tmp/experiment$ mv a/* b
reef#localhost:/tmp/experiment$ ls a
reef#localhost:/tmp/experiment$ ls b
11 22 33
It works. What are You trying to achieve? Could You please write a short example of what the input data should look like and what the output data should look like? The truth is I have no idea what You are trying to do :) Help me help You.
note that mv a/* b/ don't move files .* (file name start with '.') in a/ to b/
ex:
$ mkdir -p a/d b && touch a/f a/.f a/d/.f
$ mv a/* b/
$ ls -a a/
. .. .f
If you are copying from an ext2/3/4 file system to a FAT32 file system, and a filename has an invalid character for FAT32 naming conventions, you get this terribly annoying and incorrect as hell error message. How do I know? I wrestled with this bug - yes, it's a KERNEL BUG - for 6 hours before it dawned on me. I thought it was a shell interpreter error, I thought it was an "mv" error - I tried multiple different shells, everything. Try this experiment: on an ext file system, "touch 'a:b'" them "mv" it to a FAT32 file system. Try it, you'll enjoy (hate) the results. The same is true for '<' and '>' (\074 and \076).
Thanks for "man mv" - that's a real big help, don't quit your day job.
Might be you got the answer but above answer is not working for me.... and finally lots of researching I got the answer. (Issue is due to files-ownership)
and just put sudo before the command and its working.... :) Same thing for cp and mv command.
sudo mv -if old/* new/

Resources