When transferring files between Linux servers using SCP, many administrators encounter situations where the -p
flag doesn't fully preserve ownership as expected. This becomes particularly problematic when:
- Copying system files owned by specific service users (like mysql, postgres, or www-data)
- Operating as root due to security constraints
- Maintaining consistent permissions across environments
The -p
option in SCP preserves:
* Modification times
* Access times
* Modes (permission bits)
However, it doesn't preserve ownership because:
- SCP doesn't have privilege escalation mechanisms
- The remote server's user/group database might differ
- Security restrictions prevent arbitrary ownership changes
Option 1: Post-transfer chown
After the transfer, modify ownership:
scp -p /mysql/serv/data_summary.* some_server:/mysql/test/
ssh some_server "chown -R mysql:mysql /mysql/test/"
Option 2: rsync with sudo
For more reliable permission handling:
rsync -avz --chown=mysql:mysql /mysql/serv/data_summary.* some_server:/mysql/test/
Note: This requires sudoers configuration allowing passwordless sudo for specific commands.
For complete metadata preservation:
rsync -aAXvz --numeric-ids --rsync-path="sudo rsync" \
/mysql/serv/data_summary.* some_server:/mysql/test/
Key flags explanation:
-a
: archive mode (preserves almost everything)-A
: preserves ACLs-X
: preserves extended attributes--numeric-ids
: uses IDs instead of names for ownership
When implementing these solutions:
- Limit sudo permissions to specific commands
- Consider using SSH certificates instead of passwords
- Audit permission changes regularly
When transferring files between Linux servers using SCP, a common frustration occurs when file ownership and permissions don't carry over as expected - even when using the -p
flag. This becomes particularly problematic when:
- Moving system files owned by specific services (like mysql)
- Root is required for the transfer due to admin policies
- The destination server needs identical ownership for proper functionality
The -p
flag in SCP preserves:
- Modification times
- Access times
- Mode (permission bits)
However, it cannot preserve ownership because:
- SCP doesn't have the capability to map UIDs/GIDs between different systems
- The remote system might not have matching user/group IDs
- Even as root, SCP doesn't attempt to modify ownership during transfer
Here are three effective methods to achieve proper ownership preservation:
Method 1: Post-transfer chown
After SCP transfer, modify ownership:
scp -p /mysql/serv/data_summary.* some_server:/mysql/test/
ssh some_server "chown -R mysql:mysql /mysql/test/data_summary.*"
Method 2: rsync with --chown
rsync provides more granular control:
rsync -avp --chown=mysql:mysql /mysql/serv/data_summary.* some_server:/mysql/test/
Key advantages:
- Preserves all attributes including ownership
- Allows explicit ownership specification
- Supports incremental transfers
Method 3: Tar Pipe with Ownership Preservation
For complex transfers, consider:
(cd /mysql/serv && tar cf - data_summary.*) | \
ssh some_server "cd /mysql/test && tar xpf - --same-owner"
When implementing these solutions:
- Ensure the mysql user exists on both systems with matching UIDs
- Verify the destination directory permissions allow ownership changes
- Consider using
--numeric-ids
with rsync if UIDs differ between systems - For large transfers, monitor progress with
pv
orrsync --progress
For frequent transfers, create a bash script:
#!/bin/bash
SOURCE_PATH="/mysql/serv/data_summary.*"
DEST="some_server:/mysql/test/"
rsync -avp --chown=mysql:mysql ${SOURCE_PATH} ${DEST} || {
echo "rsync failed, falling back to scp+chown" >&2
scp -p ${SOURCE_PATH} ${DEST}
ssh ${DEST%:*} "chown mysql:mysql ${DEST#*:}data_summary.*"
}